Commit f335d92b28
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);
+ }
+}