Commit f335d92b28

matu3ba <anon_1plus1equals3@mailbox.org>
2023-10-21 11:12:02
compiler_rt: arm frsub, drsub with tests (#17629)
Tests with +-0, numbers with accuracy 0.001, 0.000001, +-max for inf.
1 parent a5c79c7
Changed files (1)
lib
compiler_rt
lib/compiler_rt/arm.zig
@@ -40,7 +40,8 @@ comptime {
                 @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = common.linkage, .visibility = common.visibility });
             }
 
-            // floating-point helper functions (double-precision reverse subtraction, y – x), see subdf3.zig
+            // floating-point helper functions (single+double-precision reverse subtraction, y – x), see subdf3.zig
+            @export(__aeabi_frsub, .{ .name = "__aeabi_frsub", .linkage = common.linkage, .visibility = common.visibility });
             @export(__aeabi_drsub, .{ .name = "__aeabi_drsub", .linkage = common.linkage, .visibility = common.visibility });
         }
     }
@@ -191,7 +192,68 @@ pub fn __aeabi_ldivmod() callconv(.Naked) void {
     unreachable;
 }
 
-pub fn __aeabi_drsub(a: f64, b: f64) callconv(.AAPCS) f64 {
+// Float Arithmetic
+
+fn __aeabi_frsub(a: f32, b: f32) callconv(.AAPCS) f32 {
+    const neg_a: f32 = @bitCast(@as(u32, @bitCast(a)) ^ (@as(u32, 1) << 31));
+    return b + neg_a;
+}
+
+fn __aeabi_drsub(a: f64, b: f64) callconv(.AAPCS) f64 {
     const neg_a: f64 = @bitCast(@as(u64, @bitCast(a)) ^ (@as(u64, 1) << 63));
     return b + neg_a;
 }
+
+test "__aeabi_frsub" {
+    if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
+    const inf32 = std.math.inf(f32);
+    const maxf32 = std.math.floatMax(f32);
+    const frsub_data = [_][3]f32{
+        [_]f32{ 0.0, 0.0, -0.0 },
+        [_]f32{ 0.0, -0.0, -0.0 },
+        [_]f32{ -0.0, 0.0, 0.0 },
+        [_]f32{ -0.0, -0.0, -0.0 },
+        [_]f32{ 0.0, 1.0, 1.0 },
+        [_]f32{ 1.0, 0.0, -1.0 },
+        [_]f32{ 1.0, 1.0, 0.0 },
+        [_]f32{ 1234.56789, 9876.54321, 8641.97532 },
+        [_]f32{ 9876.54321, 1234.56789, -8641.97532 },
+        [_]f32{ -8641.97532, 1234.56789, 9876.54321 },
+        [_]f32{ 8641.97532, 9876.54321, 1234.56789 },
+        [_]f32{ -maxf32, -maxf32, 0.0 },
+        [_]f32{ maxf32, maxf32, 0.0 },
+        [_]f32{ maxf32, -maxf32, -inf32 },
+        [_]f32{ -maxf32, maxf32, inf32 },
+    };
+    if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
+    for (frsub_data) |data| {
+        try std.testing.expectApproxEqAbs(data[2], __aeabi_frsub(data[0], data[1]), 0.001);
+    }
+}
+
+test "__aeabi_drsub" {
+    if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
+    const inf64 = std.math.inf(f64);
+    const maxf64 = std.math.floatMax(f64);
+    const frsub_data = [_][3]f64{
+        [_]f64{ 0.0, 0.0, -0.0 },
+        [_]f64{ 0.0, -0.0, -0.0 },
+        [_]f64{ -0.0, 0.0, 0.0 },
+        [_]f64{ -0.0, -0.0, -0.0 },
+        [_]f64{ 0.0, 1.0, 1.0 },
+        [_]f64{ 1.0, 0.0, -1.0 },
+        [_]f64{ 1.0, 1.0, 0.0 },
+        [_]f64{ 1234.56789, 9876.54321, 8641.97532 },
+        [_]f64{ 9876.54321, 1234.56789, -8641.97532 },
+        [_]f64{ -8641.97532, 1234.56789, 9876.54321 },
+        [_]f64{ 8641.97532, 9876.54321, 1234.56789 },
+        [_]f64{ -maxf64, -maxf64, 0.0 },
+        [_]f64{ maxf64, maxf64, 0.0 },
+        [_]f64{ maxf64, -maxf64, -inf64 },
+        [_]f64{ -maxf64, maxf64, inf64 },
+    };
+    if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;
+    for (frsub_data) |data| {
+        try std.testing.expectApproxEqAbs(data[2], __aeabi_drsub(data[0], data[1]), 0.000001);
+    }
+}