Jelajahi Sumber

no_std compatible tester

Jorge Aparicio 8 tahun lalu
induk
melakukan
b8e8c7f693

+ 8 - 3
Cargo.toml

@@ -4,17 +4,22 @@ build = "build.rs"
 name = "compiler_builtins"
 version = "0.1.0"
 
+[build-dependencies]
+rand = "0.3.15"
+
 [build-dependencies.gcc]
 optional = true
 version = "0.3.36"
 
+[target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies]
+test = { git = "https://github.com/japaric/utest" }
+utest-cortex-m-qemu = { git = "https://github.com/japaric/utest", default-features = false }
+utest-macros = { git = "https://github.com/japaric/utest" }
+
 [features]
-# Build the missing intrinsics from compiler-rt C source code
 c = ["gcc"]
-# Mark this crate as the #![compiler_builtins] crate
 compiler-builtins = []
 default = ["compiler-builtins"]
-# Include implementations of memory operations like memcpy
 mem = []
 rustbuild = ["compiler-builtins"]
 

+ 2508 - 0
build.rs

@@ -1,3 +1,5 @@
+#![feature(i128_type)]
+
 use std::env;
 
 fn main() {
@@ -15,6 +17,9 @@ fn main() {
     // custom targets, which can have arbitrary names.
     let llvm_target = target.split('-').collect::<Vec<_>>();
 
+    // Build test files
+    tests::generate();
+
     // Build missing intrinsics from compiler-rt C source code
     #[cfg(feature = "c")]
     c::compile(&llvm_target);
@@ -31,6 +36,2509 @@ fn main() {
     }
 }
 
+mod tests {
+    extern crate rand;
+
+    use std::collections::HashSet;
+    use std::fmt::Write;
+    use std::fs::File;
+    use std::hash::Hash;
+    use std::path::PathBuf;
+    use std::{env, mem};
+
+    use self::rand::Rng;
+
+    const NTESTS: usize = 10_000;
+
+    macro_rules! test {
+        ($($intrinsic:ident,)+) => {
+            $(
+                mk_file::<$intrinsic>();
+            )+
+        }
+    }
+
+    pub fn generate() {
+        // TODO move to main
+        test! {
+            // float/add.rs
+            Adddf3,
+            Addsf3,
+
+            // float/conv.rs
+            // Fixdfdi,
+            // Fixdfsi,
+            // Fixsfdi,
+            // Fixsfsi,
+            // Fixunsdfdi,
+            // Fixunsdfsi,
+            // Fixunssfdi,
+            // Fixunssfsi,
+            // Floatdidf,
+            // Floatsidf,
+            // Floatsisf,
+            // Floatundidf,
+            // Floatunsidf,
+            // Floatunsisf,
+
+            // float/pow.rs
+            Powidf2,
+            Powisf2,
+
+            // float/sub.rs
+            Subdf3,
+            Subsf3,
+
+            // int/mul.rs
+            Muldi3,
+            Mulodi4,
+            Mulosi4,
+            Muloti4,
+            Multi3,
+
+            // int/sdiv.rs
+            Divdi3,
+            Divmoddi4,
+            Divmodsi4,
+            Divsi3,
+            Divti3,
+            Moddi3,
+            Modsi3,
+            Modti3,
+
+            // int/shift.rs
+            Ashldi3,
+            Ashlti3,
+            Ashrdi3,
+            Ashrti3,
+            Lshrdi3,
+            Lshrti3,
+
+            // int/udiv.rs
+            Udivdi3,
+            Udivmoddi4,
+            Udivmodsi4,
+            Udivmodti4,
+            Udivsi3,
+            Udivti3,
+            Umoddi3,
+            Umodsi3,
+            Umodti3,
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Adddf3 {
+        a: u64,
+        b: u64,
+        c: u64,
+    }
+
+    impl TestCase for Adddf3 {
+        fn name() -> &'static str {
+            "adddf3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_f64(rng);
+            let b = gen_f64(rng);
+            let c = a + b;
+            // TODO accept NaNs. We don't do that right now because we can't check
+            // for NaN-ness on the thumb targets (due to missing intrinsics)
+            if a.is_nan() || b.is_nan() || c.is_nan() {
+                return None;
+            }
+
+            Some(
+                Adddf3 {
+                    a: to_u64(a),
+                    b: to_u64(b),
+                    c: to_u64(c),
+                },
+            )
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            r#"
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+use core::mem;
+#[cfg(not(all(target_arch = "arm",
+              not(any(target_env = "gnu", target_env = "musl")),
+              target_os = "linux",
+              test)))]
+use std::mem;
+use compiler_builtins::float::add::__adddf3;
+
+fn mk_f64(x: u64) -> f64 {
+    unsafe { mem::transmute(x) }
+}
+
+fn to_u64(x: f64) -> u64 {
+    unsafe { mem::transmute(x) }
+}
+
+static TEST_CASES: &[((u64, u64), u64)] = &[
+"#
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn adddf3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __adddf3(mk_f64(a), mk_f64(b));
+        assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Addsf3 {
+        a: u32,
+        b: u32,
+        c: u32,
+    }
+
+    impl TestCase for Addsf3 {
+        fn name() -> &'static str {
+            "addsf3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_f32(rng);
+            let b = gen_f32(rng);
+            let c = a + b;
+            // TODO accept NaNs. We don't do that right now because we can't check
+            // for NaN-ness on the thumb targets (due to missing intrinsics)
+            if a.is_nan() || b.is_nan() || c.is_nan() {
+                return None;
+            }
+
+            Some(
+                Addsf3 {
+                    a: to_u32(a),
+                    b: to_u32(b),
+                    c: to_u32(c),
+                },
+            )
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            r#"
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+use core::mem;
+#[cfg(not(all(target_arch = "arm",
+              not(any(target_env = "gnu", target_env = "musl")),
+              target_os = "linux",
+              test)))]
+use std::mem;
+use compiler_builtins::float::add::__addsf3;
+
+fn mk_f32(x: u32) -> f32 {
+    unsafe { mem::transmute(x) }
+}
+
+fn to_u32(x: f32) -> u32 {
+    unsafe { mem::transmute(x) }
+}
+
+static TEST_CASES: &[((u32, u32), u32)] = &[
+"#
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn addsf3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __addsf3(mk_f32(a), mk_f32(b));
+        assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Ashldi3 {
+        a: u64,
+        b: u32,
+        c: u64,
+    }
+
+    impl TestCase for Ashldi3 {
+        fn name() -> &'static str {
+            "ashldi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u64(rng);
+            let b = (rng.gen::<u8>() % 64) as u32;
+            let c = a << b;
+
+            Some(Ashldi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::shift::__ashldi3;
+
+static TEST_CASES: &[((u64, u32), u64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn ashldi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __ashldi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Ashlti3 {
+        a: u128,
+        b: u32,
+        c: u128,
+    }
+
+    impl TestCase for Ashlti3 {
+        fn name() -> &'static str {
+            "ashlti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u128(rng);
+            let b = (rng.gen::<u8>() % 128) as u32;
+            let c = a << b;
+
+            Some(Ashlti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::shift::__ashlti3;
+
+static TEST_CASES: &[((u128, u32), u128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn ashlti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __ashlti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Ashrdi3 {
+        a: i64,
+        b: u32,
+        c: i64,
+    }
+
+    impl TestCase for Ashrdi3 {
+        fn name() -> &'static str {
+            "ashrdi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i64(rng);
+            let b = (rng.gen::<u8>() % 64) as u32;
+            let c = a >> b;
+
+            Some(Ashrdi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::shift::__ashrdi3;
+
+static TEST_CASES: &[((i64, u32), i64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn ashrdi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __ashrdi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Ashrti3 {
+        a: i128,
+        b: u32,
+        c: i128,
+    }
+
+    impl TestCase for Ashrti3 {
+        fn name() -> &'static str {
+            "ashrti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i128(rng);
+            let b = (rng.gen::<u8>() % 128) as u32;
+            let c = a >> b;
+
+            Some(Ashrti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::shift::__ashrti3;
+
+static TEST_CASES: &[((i128, u32), i128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn ashrti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __ashrti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Divmoddi4 {
+        a: i64,
+        b: i64,
+        c: i64,
+        rem: i64,
+    }
+
+    impl TestCase for Divmoddi4 {
+        fn name() -> &'static str {
+            "divmoddi4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i64(rng);
+            let b = gen_i64(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+            let rem = a % b;
+
+            Some(Divmoddi4 { a, b, c, rem })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {rem})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                rem = self.rem
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__divmoddi4;
+
+static TEST_CASES: &[((i64, i64), (i64, i64))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn divmoddi4() {
+    for &((a, b), (c, rem)) in TEST_CASES {
+        let mut rem_ = 0;
+        let c_ = __divmoddi4(a, b, &mut rem_);
+        assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Divdi3 {
+        a: i64,
+        b: i64,
+        c: i64,
+    }
+
+    impl TestCase for Divdi3 {
+        fn name() -> &'static str {
+            "divdi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i64(rng);
+            let b = gen_i64(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+
+            Some(Divdi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__divdi3;
+
+static TEST_CASES: &[((i64, i64), i64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn divdi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __divdi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Divmodsi4 {
+        a: i32,
+        b: i32,
+        c: i32,
+        rem: i32,
+    }
+
+    impl TestCase for Divmodsi4 {
+        fn name() -> &'static str {
+            "divmodsi4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i32(rng);
+            let b = gen_i32(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+            let rem = a % b;
+
+            Some(Divmodsi4 { a, b, c, rem })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {rem})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                rem = self.rem
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__divmodsi4;
+
+static TEST_CASES: &[((i32, i32), (i32, i32))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn divmodsi4() {
+    for &((a, b), (c, rem)) in TEST_CASES {
+        let mut rem_ = 0;
+        let c_ = __divmodsi4(a, b, &mut rem_);
+        assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Divsi3 {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+
+    impl TestCase for Divsi3 {
+        fn name() -> &'static str {
+            "divsi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i32(rng);
+            let b = gen_i32(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+
+            Some(Divsi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__divsi3;
+
+static TEST_CASES: &[((i32, i32), i32)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn divsi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __divsi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Divti3 {
+        a: i128,
+        b: i128,
+        c: i128,
+    }
+
+    impl TestCase for Divti3 {
+        fn name() -> &'static str {
+            "divti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i128(rng);
+            let b = gen_i128(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+
+            Some(Divti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__divti3;
+
+static TEST_CASES: &[((i128, i128), i128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn divti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __divti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Moddi3 {
+        a: i64,
+        b: i64,
+        c: i64,
+    }
+
+    impl TestCase for Moddi3 {
+        fn name() -> &'static str {
+            "moddi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i64(rng);
+            let b = gen_i64(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a % b;
+
+            Some(Moddi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__moddi3;
+
+static TEST_CASES: &[((i64, i64), i64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn moddi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __moddi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Modsi3 {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+
+    impl TestCase for Modsi3 {
+        fn name() -> &'static str {
+            "modsi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i32(rng);
+            let b = gen_i32(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a % b;
+
+            Some(Modsi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__modsi3;
+
+static TEST_CASES: &[((i32, i32), i32)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn modsi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __modsi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Modti3 {
+        a: i128,
+        b: i128,
+        c: i128,
+    }
+
+    impl TestCase for Modti3 {
+        fn name() -> &'static str {
+            "modti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i128(rng);
+            let b = gen_i128(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a % b;
+
+            Some(Modti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::sdiv::__modti3;
+
+static TEST_CASES: &[((i128, i128), i128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn modti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __modti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    struct Muldi3 {
+        a: u64,
+        b: u64,
+        c: u64,
+    }
+
+    impl TestCase for Muldi3 {
+        fn name() -> &'static str {
+            "muldi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u64(rng);
+            let b = gen_u64(rng);
+            let c = a.wrapping_mul(b);
+
+            Some(Muldi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::mul::__muldi3;
+
+static TEST_CASES: &[((u64, u64), u64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn muldi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __muldi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Mulodi4 {
+        a: i64,
+        b: i64,
+        c: i64,
+        overflow: u32,
+    }
+
+    impl TestCase for Mulodi4 {
+        fn name() -> &'static str {
+            "mulodi4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+        {
+            let a = gen_i64(rng);
+            let b = gen_i64(rng);
+            let c = a.wrapping_mul(b);
+            let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
+
+            Some(Mulodi4 { a, b, c, overflow })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {overflow})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                overflow = self.overflow
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::mul::__mulodi4;
+
+static TEST_CASES: &[((i64, i64), (i64, i32))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn mulodi4() {
+    let mut overflow_ = 2;
+    for &((a, b), (c, overflow)) in TEST_CASES {
+        let c_ = __mulodi4(a, b, &mut overflow_);
+        assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Mulosi4 {
+        a: i32,
+        b: i32,
+        c: i32,
+        overflow: u32,
+    }
+
+    impl TestCase for Mulosi4 {
+        fn name() -> &'static str {
+            "mulosi4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+        {
+            let a = gen_i32(rng);
+            let b = gen_i32(rng);
+            let c = a.wrapping_mul(b);
+            let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
+
+            Some(Mulosi4 { a, b, c, overflow })
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::mul::__mulosi4;
+
+static TEST_CASES: &[((i32, i32), (i32, i32))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn mulosi4() {
+    let mut overflow_ = 2;
+    for &((a, b), (c, overflow)) in TEST_CASES {
+        let c_ = __mulosi4(a, b, &mut overflow_);
+        assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
+    }
+}
+"
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {overflow})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                overflow = self.overflow
+            )
+                    .unwrap();
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Muloti4 {
+        a: i128,
+        b: i128,
+        c: i128,
+        overflow: u32,
+    }
+
+    impl TestCase for Muloti4 {
+        fn name() -> &'static str {
+            "muloti4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+        {
+            let a = gen_i128(rng);
+            let b = gen_i128(rng);
+            let c = a.wrapping_mul(b);
+            let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
+
+            Some(Muloti4 { a, b, c, overflow })
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::mul::__muloti4;
+
+static TEST_CASES: &[((i128, i128), (i128, i32))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn muloti4() {
+    let mut overflow_ = 2;
+    for &((a, b), (c, overflow)) in TEST_CASES {
+        let c_ = __muloti4(a, b, &mut overflow_);
+        assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
+    }
+}
+"
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {overflow})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                overflow = self.overflow
+            )
+                    .unwrap();
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Multi3 {
+        a: i128,
+        b: i128,
+        c: i128,
+    }
+
+    impl TestCase for Multi3 {
+        fn name() -> &'static str {
+            "multi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_i128(rng);
+            let b = gen_i128(rng);
+            let c = a.wrapping_mul(b);
+
+            Some(Multi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::mul::__multi3;
+
+static TEST_CASES: &[((i128, i128), i128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn multi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __multi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Powidf2 {
+        a: u64,
+        b: i32,
+        c: u64,
+    }
+
+    impl TestCase for Powidf2 {
+        fn name() -> &'static str {
+            "powidf2"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_f64(rng);
+            let b = gen_i32(rng);
+            let c = a.powi(b);
+            // TODO accept NaNs. We don't do that right now because we can't check
+            // for NaN-ness on the thumb targets
+            if a.is_nan() || c.is_nan() {
+                return None;
+            }
+
+            Some(
+                Powidf2 {
+                    a: to_u64(a),
+                    b,
+                    c: to_u64(c),
+                },
+            )
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            r#"
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+use core::mem;
+#[cfg(not(all(target_arch = "arm",
+              not(any(target_env = "gnu", target_env = "musl")),
+              target_os = "linux",
+              test)))]
+use std::mem;
+use compiler_builtins::float::pow::__powidf2;
+
+fn mk_f64(x: u64) -> f64 {
+    unsafe { mem::transmute(x) }
+}
+
+fn to_u64(x: f64) -> u64 {
+    unsafe { mem::transmute(x) }
+}
+
+static TEST_CASES: &[((u64, i32), u64)] = &[
+"#
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn powidf2() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __powidf2(mk_f64(a), b);
+        assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Powisf2 {
+        a: u32,
+        b: i32,
+        c: u32,
+    }
+
+    impl TestCase for Powisf2 {
+        fn name() -> &'static str {
+            "powisf2"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_f32(rng);
+            let b = gen_i32(rng);
+            let c = a.powi(b);
+            // TODO accept NaNs. We don't do that right now because we can't check
+            // for NaN-ness on the thumb targets
+            if a.is_nan() || c.is_nan() {
+                return None;
+            }
+
+            Some(
+                Powisf2 {
+                    a: to_u32(a),
+                    b,
+                    c: to_u32(c),
+                },
+            )
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            r#"
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+use core::mem;
+#[cfg(not(all(target_arch = "arm",
+              not(any(target_env = "gnu", target_env = "musl")),
+              target_os = "linux",
+              test)))]
+use std::mem;
+use compiler_builtins::float::pow::__powisf2;
+
+fn mk_f32(x: u32) -> f32 {
+    unsafe { mem::transmute(x) }
+}
+
+fn to_u32(x: f32) -> u32 {
+    unsafe { mem::transmute(x) }
+}
+
+static TEST_CASES: &[((u32, i32), u32)] = &[
+"#
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn powisf2() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __powisf2(mk_f32(a), b);
+        assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Lshrdi3 {
+        a: u64,
+        b: u32,
+        c: u64,
+    }
+
+    impl TestCase for Lshrdi3 {
+        fn name() -> &'static str {
+            "lshrdi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u64(rng);
+            let b = (rng.gen::<u8>() % 64) as u32;
+            let c = a >> b;
+
+            Some(Lshrdi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::shift::__lshrdi3;
+
+static TEST_CASES: &[((u64, u32), u64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn lshrdi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __lshrdi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Lshrti3 {
+        a: u128,
+        b: u32,
+        c: u128,
+    }
+
+    impl TestCase for Lshrti3 {
+        fn name() -> &'static str {
+            "lshrti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u128(rng);
+            let b = (rng.gen::<u8>() % 128) as u32;
+            let c = a >> b;
+
+            Some(Lshrti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::shift::__lshrti3;
+
+static TEST_CASES: &[((u128, u32), u128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn lshrti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __lshrti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Subdf3 {
+        a: u64,
+        b: u64,
+        c: u64,
+    }
+
+    impl TestCase for Subdf3 {
+        fn name() -> &'static str {
+            "subdf3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_f64(rng);
+            let b = gen_f64(rng);
+            let c = a - b;
+            // TODO accept NaNs. We don't do that right now because we can't check
+            // for NaN-ness on the thumb targets (due to missing intrinsics)
+            if a.is_nan() || b.is_nan() || c.is_nan() {
+                return None;
+            }
+
+            Some(
+                Subdf3 {
+                    a: to_u64(a),
+                    b: to_u64(b),
+                    c: to_u64(c),
+                },
+            )
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            r#"
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+use core::mem;
+#[cfg(not(all(target_arch = "arm",
+              not(any(target_env = "gnu", target_env = "musl")),
+              target_os = "linux",
+              test)))]
+use std::mem;
+use compiler_builtins::float::sub::__subdf3;
+
+fn mk_f64(x: u64) -> f64 {
+    unsafe { mem::transmute(x) }
+}
+
+fn to_u64(x: f64) -> u64 {
+    unsafe { mem::transmute(x) }
+}
+
+static TEST_CASES: &[((u64, u64), u64)] = &[
+"#
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn subdf3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __subdf3(mk_f64(a), mk_f64(b));
+        assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Subsf3 {
+        a: u32,
+        b: u32,
+        c: u32,
+    }
+
+    impl TestCase for Subsf3 {
+        fn name() -> &'static str {
+            "subsf3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_f32(rng);
+            let b = gen_f32(rng);
+            let c = a - b;
+            // TODO accept NaNs. We don't do that right now because we can't check
+            // for NaN-ness on the thumb targets (due to missing intrinsics)
+            if a.is_nan() || b.is_nan() || c.is_nan() {
+                return None;
+            }
+
+            Some(
+                Subsf3 {
+                    a: to_u32(a),
+                    b: to_u32(b),
+                    c: to_u32(c),
+                },
+            )
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            r#"
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+use core::mem;
+#[cfg(not(all(target_arch = "arm",
+              not(any(target_env = "gnu", target_env = "musl")),
+              target_os = "linux",
+              test)))]
+use std::mem;
+use compiler_builtins::float::sub::__subsf3;
+
+fn mk_f32(x: u32) -> f32 {
+    unsafe { mem::transmute(x) }
+}
+
+fn to_u32(x: f32) -> u32 {
+    unsafe { mem::transmute(x) }
+}
+
+static TEST_CASES: &[((u32, u32), u32)] = &[
+"#
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn subsf3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __subsf3(mk_f32(a), mk_f32(b));
+        assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Udivdi3 {
+        a: u64,
+        b: u64,
+        c: u64,
+    }
+
+    impl TestCase for Udivdi3 {
+        fn name() -> &'static str {
+            "udivdi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u64(rng);
+            let b = gen_u64(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+
+            Some(Udivdi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__udivdi3;
+
+static TEST_CASES: &[((u64, u64), u64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn udivdi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __udivdi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Udivmoddi4 {
+        a: u64,
+        b: u64,
+        c: u64,
+        rem: u64,
+    }
+
+    impl TestCase for Udivmoddi4 {
+        fn name() -> &'static str {
+            "udivmoddi4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u64(rng);
+            let b = gen_u64(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+            let rem = a % b;
+
+            Some(Udivmoddi4 { a, b, c, rem })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {rem})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                rem = self.rem
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__udivmoddi4;
+
+static TEST_CASES: &[((u64, u64), (u64, u64))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn udivmoddi4() {
+    for &((a, b), (c, rem)) in TEST_CASES {
+        let mut rem_ = 0;
+        let c_ = __udivmoddi4(a, b, Some(&mut rem_));
+        assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Udivmodsi4 {
+        a: u32,
+        b: u32,
+        c: u32,
+        rem: u32,
+    }
+
+    impl TestCase for Udivmodsi4 {
+        fn name() -> &'static str {
+            "udivmodsi4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u32(rng);
+            let b = gen_u32(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+            let rem = a % b;
+
+            Some(Udivmodsi4 { a, b, c, rem })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {rem})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                rem = self.rem
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__udivmodsi4;
+
+static TEST_CASES: &[((u32, u32), (u32, u32))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn udivmodsi4() {
+    for &((a, b), (c, rem)) in TEST_CASES {
+        let mut rem_ = 0;
+        let c_ = __udivmodsi4(a, b, Some(&mut rem_));
+        assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Udivmodti4 {
+        a: u128,
+        b: u128,
+        c: u128,
+        rem: u128,
+    }
+
+    impl TestCase for Udivmodti4 {
+        fn name() -> &'static str {
+            "udivmodti4"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u128(rng);
+            let b = gen_u128(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+            let rem = a % b;
+
+            Some(Udivmodti4 { a, b, c, rem })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), ({c}, {rem})),",
+                a = self.a,
+                b = self.b,
+                c = self.c,
+                rem = self.rem
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__udivmodti4;
+
+static TEST_CASES: &[((u128, u128), (u128, u128))] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn udivmodti4() {
+    for &((a, b), (c, rem)) in TEST_CASES {
+        let mut rem_ = 0;
+        let c_ = __udivmodti4(a, b, Some(&mut rem_));
+        assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Udivsi3 {
+        a: u32,
+        b: u32,
+        c: u32,
+    }
+
+    impl TestCase for Udivsi3 {
+        fn name() -> &'static str {
+            "udivsi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u32(rng);
+            let b = gen_u32(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+
+            Some(Udivsi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__udivsi3;
+
+static TEST_CASES: &[((u32, u32), u32)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn udivsi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __udivsi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Udivti3 {
+        a: u128,
+        b: u128,
+        c: u128,
+    }
+
+    impl TestCase for Udivti3 {
+        fn name() -> &'static str {
+            "udivti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u128(rng);
+            let b = gen_u128(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a / b;
+
+            Some(Udivti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__udivti3;
+
+static TEST_CASES: &[((u128, u128), u128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn udivti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __udivti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Umoddi3 {
+        a: u64,
+        b: u64,
+        c: u64,
+    }
+
+    impl TestCase for Umoddi3 {
+        fn name() -> &'static str {
+            "umoddi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u64(rng);
+            let b = gen_u64(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a % b;
+
+            Some(Umoddi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__umoddi3;
+
+static TEST_CASES: &[((u64, u64), u64)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn umoddi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __umoddi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Umodsi3 {
+        a: u32,
+        b: u32,
+        c: u32,
+    }
+
+    impl TestCase for Umodsi3 {
+        fn name() -> &'static str {
+            "umodsi3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u32(rng);
+            let b = gen_u32(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a % b;
+
+            Some(Umodsi3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__umodsi3;
+
+static TEST_CASES: &[((u32, u32), u32)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn umodsi3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __umodsi3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    #[derive(Eq, Hash, PartialEq)]
+    pub struct Umodti3 {
+        a: u128,
+        b: u128,
+        c: u128,
+    }
+
+    impl TestCase for Umodti3 {
+        fn name() -> &'static str {
+            "umodti3"
+        }
+
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized,
+        {
+            let a = gen_u128(rng);
+            let b = gen_u128(rng);
+            if b == 0 {
+                return None;
+            }
+            let c = a % b;
+
+            Some(Umodti3 { a, b, c })
+        }
+
+        fn to_string(&self, buffer: &mut String) {
+            writeln!(
+                buffer,
+                "(({a}, {b}), {c}),",
+                a = self.a,
+                b = self.b,
+                c = self.c
+            )
+                    .unwrap();
+        }
+
+        fn prologue() -> &'static str {
+            "
+use compiler_builtins::int::udiv::__umodti3;
+
+static TEST_CASES: &[((u128, u128), u128)] = &[
+"
+        }
+
+        fn epilogue() -> &'static str {
+            "
+];
+
+#[test]
+fn umodti3() {
+    for &((a, b), c) in TEST_CASES {
+        let c_ = __umodti3(a, b);
+        assert_eq!(((a, b), c), ((a, b), c_));
+    }
+}
+"
+        }
+    }
+
+    trait TestCase {
+        /// Name of the intrinsic to test
+        fn name() -> &'static str;
+        /// Generates a valid test case
+        fn generate<R>(rng: &mut R) -> Option<Self>
+        where
+            R: Rng,
+            Self: Sized;
+        /// Stringifies a test case
+        fn to_string(&self, buffer: &mut String);
+        /// Prologue of the test file
+        fn prologue() -> &'static str;
+        /// Epilogue of the test file
+        fn epilogue() -> &'static str;
+    }
+
+    const PROLOGUE: &'static str = r#"
+extern crate compiler_builtins;
+
+// test runner
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+extern crate utest_cortex_m_qemu;
+
+// overrides `panic!`
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+#[macro_use]
+extern crate utest_macros;
+
+#[cfg(all(target_arch = "arm",
+          not(any(target_env = "gnu", target_env = "musl")),
+          target_os = "linux",
+          test))]
+macro_rules! panic {
+    ($($tt:tt)*) => {
+        upanic!($($tt)*);
+    };
+}
+"#;
+
+    macro_rules! gen_int {
+        ($name:ident, $ity:ident, $hty:ident) => {
+            fn $name<R>(rng: &mut R) -> $ity
+                where
+                R: Rng,
+            {
+                let mut mk = || if rng.gen_weighted_bool(10) {
+                    *rng.choose(&[::std::$hty::MAX, 0, ::std::$hty::MIN]).unwrap()
+                } else {
+                    rng.gen::<$hty>()
+                };
+                unsafe { mem::transmute([mk(), mk()]) }
+            }
+
+        }
+    }
+
+    gen_int!(gen_i32, i32, i16);
+    gen_int!(gen_i64, i64, i32);
+    gen_int!(gen_i128, i128, i64);
+
+    macro_rules! gen_float {
+        ($name:ident,
+         $fty:ident,
+         $uty:ident,
+         $bits:expr,
+         $significand_bits:expr) => {
+            pub fn $name<R>(rng: &mut R) -> $fty
+            where
+                R: Rng,
+            {
+                const BITS: u8 = $bits;
+                const SIGNIFICAND_BITS: u8 = $significand_bits;
+
+                const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1;
+                const SIGN_MASK: $uty = (1 << (BITS - 1));
+                const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK);
+
+                fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty {
+                    unsafe {
+                        mem::transmute(((sign as $uty) << (BITS - 1)) |
+                                       ((exponent & EXPONENT_MASK) <<
+                                        SIGNIFICAND_BITS) |
+                                       (significand & SIGNIFICAND_MASK))
+                    }
+                }
+
+                if rng.gen_weighted_bool(10) {
+                    // Special values
+                    *rng.choose(&[-0.0,
+                                  0.0,
+                                  ::std::$fty::NAN,
+                                  ::std::$fty::INFINITY,
+                                  -::std::$fty::INFINITY])
+                        .unwrap()
+                } else if rng.gen_weighted_bool(10) {
+                    // NaN patterns
+                    mk_f32(rng.gen(), rng.gen(), 0)
+                } else if rng.gen() {
+                    // Denormalized
+                    mk_f32(rng.gen(), 0, rng.gen())
+                } else {
+                    // Random anything
+                    mk_f32(rng.gen(), rng.gen(), rng.gen())
+                }
+            }
+        }
+    }
+
+    gen_float!(gen_f32, f32, u32, 32, 23);
+    gen_float!(gen_f64, f64, u64, 64, 52);
+
+    pub fn gen_u128<R>(rng: &mut R) -> u128
+    where
+        R: Rng,
+    {
+        gen_i128(rng) as u128
+    }
+
+    pub fn gen_u32<R>(rng: &mut R) -> u32
+    where
+        R: Rng,
+    {
+        gen_i32(rng) as u32
+    }
+
+    fn gen_u64<R>(rng: &mut R) -> u64
+    where
+        R: Rng,
+    {
+        gen_i64(rng) as u64
+    }
+
+    pub fn to_u32(x: f32) -> u32 {
+        unsafe { mem::transmute(x) }
+    }
+
+    pub fn to_u64(x: f64) -> u64 {
+        unsafe { mem::transmute(x) }
+    }
+
+    fn mk_tests<T, R>(mut n: usize, rng: &mut R) -> String
+    where
+        T: Eq + Hash + TestCase,
+        R: Rng,
+    {
+        let mut buffer = PROLOGUE.to_owned();
+        buffer.push_str(T::prologue());
+        let mut cases = HashSet::new();
+        while n != 0 {
+            if let Some(case) = T::generate(rng) {
+                if cases.contains(&case) {
+                    continue;
+                }
+                case.to_string(&mut buffer);
+                n -= 1;
+                cases.insert(case);
+            }
+        }
+        buffer.push_str(T::epilogue());
+        buffer
+    }
+
+    fn mk_file<T>()
+    where
+        T: Eq + Hash + TestCase,
+    {
+        use std::io::Write;
+
+        let rng = &mut rand::thread_rng();
+        let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+        let out_file = out_dir.join(format!("{}.rs", T::name()));
+        let contents = mk_tests::<T, _>(NTESTS, rng);
+
+        File::create(out_file)
+            .unwrap()
+            .write_all(contents.as_bytes())
+            .unwrap();
+    }
+}
+
 #[cfg(feature = "c")]
 mod c {
     extern crate gcc;

+ 1 - 0
src/float/conv.rs

@@ -94,6 +94,7 @@ enum Sign {
     Positive,
     Negative
 }
+
 macro_rules! fp_fix {
     ($intrinsic:ident: $fty:ty, $ity:ty) => {
         pub extern "C" fn $intrinsic(f: $fty) -> $ity {

+ 8 - 0
tests/adddf3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/adddf3.rs"));

+ 8 - 0
tests/addsf3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/addsf3.rs"));

+ 8 - 0
tests/ashldi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/ashldi3.rs"));

+ 8 - 0
tests/ashlti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/ashlti3.rs"));

+ 8 - 0
tests/ashrdi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/ashrdi3.rs"));

+ 8 - 0
tests/ashrti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/ashrti3.rs"));

+ 8 - 0
tests/divdi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/divdi3.rs"));

+ 8 - 0
tests/divmoddi4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/divmoddi4.rs"));

+ 8 - 0
tests/divmodsi4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/divmodsi4.rs"));

+ 8 - 0
tests/divsi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/divsi3.rs"));

+ 8 - 0
tests/divti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/divti3.rs"));

+ 8 - 0
tests/lshrdi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/lshrdi3.rs"));

+ 8 - 0
tests/lshrti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/lshrti3.rs"));

+ 8 - 0
tests/moddi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/moddi3.rs"));

+ 8 - 0
tests/modsi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/modsi3.rs"));

+ 8 - 0
tests/modti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/modti3.rs"));

+ 8 - 0
tests/muldi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/muldi3.rs"));

+ 8 - 0
tests/mulodi4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/mulodi4.rs"));

+ 8 - 0
tests/mulosi4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/mulosi4.rs"));

+ 8 - 0
tests/muloti4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/muloti4.rs"));

+ 8 - 0
tests/multi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/multi3.rs"));

+ 8 - 0
tests/powidf2.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/powidf2.rs"));

+ 8 - 0
tests/powisf2.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/powisf2.rs"));

+ 8 - 0
tests/subdf3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/subdf3.rs"));

+ 8 - 0
tests/subsf3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/subsf3.rs"));

+ 8 - 0
tests/udivdi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/udivdi3.rs"));

+ 8 - 0
tests/udivmoddi4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/udivmoddi4.rs"));

+ 8 - 0
tests/udivmodsi4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/udivmodsi4.rs"));

+ 8 - 0
tests/udivmodti4.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/udivmodti4.rs"));

+ 8 - 0
tests/udivsi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/udivsi3.rs"));

+ 8 - 0
tests/udivti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/udivti3.rs"));

+ 8 - 0
tests/umoddi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/umoddi3.rs"));

+ 8 - 0
tests/umodsi3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/umodsi3.rs"));

+ 8 - 0
tests/umodti3.rs

@@ -0,0 +1,8 @@
+#![feature(compiler_builtins_lib)]
+#![feature(i128_type)]
+#![cfg_attr(all(target_arch = "arm",
+                not(any(target_env = "gnu", target_env = "musl")),
+                target_os = "linux",
+                test), no_std)]
+
+include!(concat!(env!("OUT_DIR"), "/umodti3.rs"));

+ 24 - 0
thumbv6m-linux-eabi.json

@@ -0,0 +1,24 @@
+{
+    "abi-blacklist": [
+        "stdcall",
+        "fastcall",
+        "vectorcall",
+        "win64",
+        "sysv64"
+    ],
+    "arch": "arm",
+    "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
+    "env": "",
+    "executables": true,
+    "features": "+strict-align",
+    "linker": "arm-none-eabi-gcc",
+    "llvm-target": "thumbv6m-none-eabi",
+    "max-atomic-width": 0,
+    "os": "linux",
+    "panic-strategy": "abort",
+    "pre-link-args": ["-nostartfiles"],
+    "relocation-model": "static",
+    "target-endian": "little",
+    "target-pointer-width": "32",
+    "vendor": ""
+}

+ 23 - 0
thumbv7em-linux-eabi.json

@@ -0,0 +1,23 @@
+{
+    "abi-blacklist": [
+        "stdcall",
+        "fastcall",
+        "vectorcall",
+        "win64",
+        "sysv64"
+    ],
+    "arch": "arm",
+    "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
+    "env": "",
+    "executables": true,
+    "linker": "arm-none-eabi-gcc",
+    "llvm-target": "thumbv7em-none-eabi",
+    "max-atomic-width": 32,
+    "os": "linux",
+    "panic-strategy": "abort",
+    "pre-link-args": ["-nostartfiles"],
+    "relocation-model": "static",
+    "target-endian": "little",
+    "target-pointer-width": "32",
+    "vendor": ""
+}

+ 24 - 0
thumbv7em-linux-eabihf.json

@@ -0,0 +1,24 @@
+{
+    "abi-blacklist": [
+        "stdcall",
+        "fastcall",
+        "vectorcall",
+        "win64",
+        "sysv64"
+    ],
+    "arch": "arm",
+    "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
+    "env": "",
+    "executables": true,
+    "features": "+vfp4,+d16,+fp-only-sp",
+    "linker": "arm-none-eabi-gcc",
+    "llvm-target": "thumbv7em-none-eabihf",
+    "max-atomic-width": 32,
+    "os": "linux",
+    "panic-strategy": "abort",
+    "pre-link-args": ["-nostartfiles"],
+    "relocation-model": "static",
+    "target-endian": "little",
+    "target-pointer-width": "32",
+    "vendor": ""
+}

+ 23 - 0
thumbv7m-linux-eabi.json

@@ -0,0 +1,23 @@
+{
+    "abi-blacklist": [
+        "stdcall",
+        "fastcall",
+        "vectorcall",
+        "win64",
+        "sysv64"
+    ],
+    "arch": "arm",
+    "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
+    "env": "",
+    "executables": true,
+    "linker": "arm-none-eabi-gcc",
+    "llvm-target": "thumbv7m-none-eabi",
+    "max-atomic-width": 32,
+    "os": "linux",
+    "panic-strategy": "abort",
+    "pre-link-args": ["-nostartfiles"],
+    "relocation-model": "static",
+    "target-endian": "little",
+    "target-pointer-width": "32",
+    "vendor": ""
+}