From 0d533433e21621177fb291e2a4901bee11834501 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Fri, 7 Oct 2022 10:19:08 -0700 Subject: [PATCH] compiler_rt: Add missing `f16` functions This change also exposes some of the existing functions under both the PPC-style names symbols and the compiler-rt-style names, since Zig currently lowers softfloat calls to the latter. --- lib/compiler_rt.zig | 24 +++++++++++----- lib/compiler_rt/addhf3.zig | 12 ++++++++ lib/compiler_rt/cmphf2.zig | 50 +++++++++++++++++++++++++++++++++ lib/compiler_rt/divhf3.zig | 11 ++++++++ lib/compiler_rt/extendhfdf2.zig | 12 ++++++++ lib/compiler_rt/extendhfsf2.zig | 9 ++---- lib/compiler_rt/gehf2.zig | 31 ++++++++++++++++++++ lib/compiler_rt/mulf3.zig | 5 ++-- lib/compiler_rt/mulhf3.zig | 12 ++++++++ lib/compiler_rt/neghf2.zig | 11 ++++++++ lib/compiler_rt/subhf3.zig | 12 ++++++++ lib/compiler_rt/tan.zig | 6 ++-- lib/compiler_rt/truncsfhf2.zig | 9 ++---- lib/compiler_rt/unordhf2.zig | 12 ++++++++ lib/compiler_rt/unordxf2.zig | 12 ++++++++ 15 files changed, 203 insertions(+), 25 deletions(-) create mode 100644 lib/compiler_rt/addhf3.zig create mode 100644 lib/compiler_rt/cmphf2.zig create mode 100644 lib/compiler_rt/divhf3.zig create mode 100644 lib/compiler_rt/extendhfdf2.zig create mode 100644 lib/compiler_rt/gehf2.zig create mode 100644 lib/compiler_rt/mulhf3.zig create mode 100644 lib/compiler_rt/neghf2.zig create mode 100644 lib/compiler_rt/subhf3.zig create mode 100644 lib/compiler_rt/unordhf2.zig create mode 100644 lib/compiler_rt/unordxf2.zig diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index d261c49ff1..1597b7e135 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -4,17 +4,20 @@ comptime { _ = @import("compiler_rt/atomics.zig"); _ = @import("compiler_rt/addf3.zig"); + _ = @import("compiler_rt/addhf3.zig"); _ = @import("compiler_rt/addsf3.zig"); _ = @import("compiler_rt/adddf3.zig"); _ = @import("compiler_rt/addtf3.zig"); _ = @import("compiler_rt/addxf3.zig"); + _ = @import("compiler_rt/subhf3.zig"); _ = @import("compiler_rt/subsf3.zig"); _ = @import("compiler_rt/subdf3.zig"); _ = @import("compiler_rt/subtf3.zig"); _ = @import("compiler_rt/subxf3.zig"); _ = @import("compiler_rt/mulf3.zig"); + _ = @import("compiler_rt/mulhf3.zig"); _ = @import("compiler_rt/mulsf3.zig"); _ = @import("compiler_rt/muldf3.zig"); _ = @import("compiler_rt/multf3.zig"); @@ -34,51 +37,58 @@ comptime { _ = @import("compiler_rt/divxc3.zig"); _ = @import("compiler_rt/divtc3.zig"); + _ = @import("compiler_rt/neghf2.zig"); _ = @import("compiler_rt/negsf2.zig"); _ = @import("compiler_rt/negdf2.zig"); _ = @import("compiler_rt/negtf2.zig"); _ = @import("compiler_rt/negxf2.zig"); _ = @import("compiler_rt/comparef.zig"); + _ = @import("compiler_rt/cmphf2.zig"); _ = @import("compiler_rt/cmpsf2.zig"); _ = @import("compiler_rt/cmpdf2.zig"); _ = @import("compiler_rt/cmptf2.zig"); _ = @import("compiler_rt/cmpxf2.zig"); + _ = @import("compiler_rt/gehf2.zig"); _ = @import("compiler_rt/gesf2.zig"); _ = @import("compiler_rt/gedf2.zig"); - _ = @import("compiler_rt/getf2.zig"); _ = @import("compiler_rt/gexf2.zig"); + _ = @import("compiler_rt/getf2.zig"); + _ = @import("compiler_rt/unordhf2.zig"); _ = @import("compiler_rt/unordsf2.zig"); _ = @import("compiler_rt/unorddf2.zig"); + _ = @import("compiler_rt/unordxf2.zig"); _ = @import("compiler_rt/unordtf2.zig"); _ = @import("compiler_rt/extendf.zig"); - _ = @import("compiler_rt/extenddftf2.zig"); - _ = @import("compiler_rt/extenddfxf2.zig"); _ = @import("compiler_rt/extendhfsf2.zig"); + _ = @import("compiler_rt/extendhfdf2.zig"); _ = @import("compiler_rt/extendhftf2.zig"); _ = @import("compiler_rt/extendhfxf2.zig"); _ = @import("compiler_rt/extendsfdf2.zig"); _ = @import("compiler_rt/extendsftf2.zig"); _ = @import("compiler_rt/extendsfxf2.zig"); + _ = @import("compiler_rt/extenddftf2.zig"); + _ = @import("compiler_rt/extenddfxf2.zig"); _ = @import("compiler_rt/extendxftf2.zig"); _ = @import("compiler_rt/truncf.zig"); _ = @import("compiler_rt/truncsfhf2.zig"); _ = @import("compiler_rt/truncdfhf2.zig"); _ = @import("compiler_rt/truncdfsf2.zig"); + _ = @import("compiler_rt/truncxfhf2.zig"); + _ = @import("compiler_rt/truncxfsf2.zig"); + _ = @import("compiler_rt/truncxfdf2.zig"); _ = @import("compiler_rt/trunctfhf2.zig"); _ = @import("compiler_rt/trunctfsf2.zig"); _ = @import("compiler_rt/trunctfdf2.zig"); _ = @import("compiler_rt/trunctfxf2.zig"); - _ = @import("compiler_rt/truncxfhf2.zig"); - _ = @import("compiler_rt/truncxfsf2.zig"); - _ = @import("compiler_rt/truncxfdf2.zig"); - _ = @import("compiler_rt/divtf3.zig"); + _ = @import("compiler_rt/divhf3.zig"); _ = @import("compiler_rt/divsf3.zig"); _ = @import("compiler_rt/divdf3.zig"); _ = @import("compiler_rt/divxf3.zig"); + _ = @import("compiler_rt/divtf3.zig"); _ = @import("compiler_rt/sin.zig"); _ = @import("compiler_rt/cos.zig"); _ = @import("compiler_rt/sincos.zig"); diff --git a/lib/compiler_rt/addhf3.zig b/lib/compiler_rt/addhf3.zig new file mode 100644 index 0000000000..12086aef38 --- /dev/null +++ b/lib/compiler_rt/addhf3.zig @@ -0,0 +1,12 @@ +const common = @import("./common.zig"); +const addf3 = @import("./addf3.zig").addf3; + +pub const panic = common.panic; + +comptime { + @export(__addhf3, .{ .name = "__addhf3", .linkage = common.linkage }); +} + +fn __addhf3(a: f16, b: f16) callconv(.C) f16 { + return addf3(f16, a, b); +} diff --git a/lib/compiler_rt/cmphf2.zig b/lib/compiler_rt/cmphf2.zig new file mode 100644 index 0000000000..d5ee3f1daa --- /dev/null +++ b/lib/compiler_rt/cmphf2.zig @@ -0,0 +1,50 @@ +///! The quoted behavior definitions are from +///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines +const common = @import("./common.zig"); +const comparef = @import("./comparef.zig"); + +pub const panic = common.panic; + +comptime { + @export(__eqhf2, .{ .name = "__eqhf2", .linkage = common.linkage }); + @export(__nehf2, .{ .name = "__nehf2", .linkage = common.linkage }); + @export(__lehf2, .{ .name = "__lehf2", .linkage = common.linkage }); + @export(__cmphf2, .{ .name = "__cmphf2", .linkage = common.linkage }); + @export(__lthf2, .{ .name = "__lthf2", .linkage = common.linkage }); +} + +/// "These functions calculate a <=> b. That is, if a is less than b, they return -1; +/// if a is greater than b, they return 1; and if a and b are equal they return 0. +/// If either argument is NaN they return 1..." +/// +/// Note that this matches the definition of `__lehf2`, `__eqhf2`, `__nehf2`, `__cmphf2`, +/// and `__lthf2`. +fn __cmphf2(a: f16, b: f16) callconv(.C) i32 { + return @enumToInt(comparef.cmpf2(f16, comparef.LE, a, b)); +} + +/// "These functions return a value less than or equal to zero if neither argument is NaN, +/// and a is less than or equal to b." +pub fn __lehf2(a: f16, b: f16) callconv(.C) i32 { + return __cmphf2(a, b); +} + +/// "These functions return zero if neither argument is NaN, and a and b are equal." +/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined +/// to have the same return value. +pub fn __eqhf2(a: f16, b: f16) callconv(.C) i32 { + return __cmphf2(a, b); +} + +/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." +/// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined +/// to have the same return value. +pub fn __nehf2(a: f16, b: f16) callconv(.C) i32 { + return __cmphf2(a, b); +} + +/// "These functions return a value less than zero if neither argument is NaN, and a +/// is strictly less than b." +pub fn __lthf2(a: f16, b: f16) callconv(.C) i32 { + return __cmphf2(a, b); +} diff --git a/lib/compiler_rt/divhf3.zig b/lib/compiler_rt/divhf3.zig new file mode 100644 index 0000000000..ad73a5ddb2 --- /dev/null +++ b/lib/compiler_rt/divhf3.zig @@ -0,0 +1,11 @@ +const common = @import("common.zig"); +const divsf3 = @import("./divsf3.zig"); + +comptime { + @export(__divhf3, .{ .name = "__divhf3", .linkage = common.linkage }); +} + +pub fn __divhf3(a: f16, b: f16) callconv(.C) f16 { + // TODO: more efficient implementation + return @floatCast(f16, divsf3.__divsf3(a, b)); +} diff --git a/lib/compiler_rt/extendhfdf2.zig b/lib/compiler_rt/extendhfdf2.zig new file mode 100644 index 0000000000..f7a94f58ef --- /dev/null +++ b/lib/compiler_rt/extendhfdf2.zig @@ -0,0 +1,12 @@ +const common = @import("./common.zig"); +const extendf = @import("./extendf.zig").extendf; + +pub const panic = common.panic; + +comptime { + @export(__extendhfdf2, .{ .name = "__extendhfdf2", .linkage = common.linkage }); +} + +pub fn __extendhfdf2(a: common.F16T) callconv(.C) f64 { + return extendf(f64, f16, @bitCast(u16, a)); +} diff --git a/lib/compiler_rt/extendhfsf2.zig b/lib/compiler_rt/extendhfsf2.zig index a6bf5f5be5..0c204ec188 100644 --- a/lib/compiler_rt/extendhfsf2.zig +++ b/lib/compiler_rt/extendhfsf2.zig @@ -5,22 +5,17 @@ pub const panic = common.panic; comptime { if (common.gnu_f16_abi) { - @export(__gnu_h2f_ieee, .{ .name = "__gnu_h2f_ieee", .linkage = common.linkage }); + @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = common.linkage }); } else if (common.want_aeabi) { @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = common.linkage }); - } else { - @export(__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = common.linkage }); } + @export(__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = common.linkage }); } pub fn __extendhfsf2(a: common.F16T) callconv(.C) f32 { return extendf(f32, f16, @bitCast(u16, a)); } -fn __gnu_h2f_ieee(a: common.F16T) callconv(.C) f32 { - return extendf(f32, f16, @bitCast(u16, a)); -} - fn __aeabi_h2f(a: u16) callconv(.AAPCS) f32 { return extendf(f32, f16, @bitCast(u16, a)); } diff --git a/lib/compiler_rt/gehf2.zig b/lib/compiler_rt/gehf2.zig new file mode 100644 index 0000000000..651cbf943f --- /dev/null +++ b/lib/compiler_rt/gehf2.zig @@ -0,0 +1,31 @@ +///! The quoted behavior definitions are from +///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines +const common = @import("./common.zig"); +const comparef = @import("./comparef.zig"); + +pub const panic = common.panic; + +comptime { + @export(__gehf2, .{ .name = "__gehf2", .linkage = common.linkage }); + @export(__gthf2, .{ .name = "__gthf2", .linkage = common.linkage }); +} + +/// "These functions return a value greater than or equal to zero if neither +/// argument is NaN, and a is greater than or equal to b." +pub fn __gehf2(a: f16, b: f16) callconv(.C) i32 { + return @enumToInt(comparef.cmpf2(f16, comparef.GE, a, b)); +} + +/// "These functions return a value greater than zero if neither argument is NaN, +/// and a is strictly greater than b." +pub fn __gthf2(a: f16, b: f16) callconv(.C) i32 { + return __gehf2(a, b); +} + +fn __aeabi_fcmpge(a: f16, b: f16) callconv(.AAPCS) i32 { + return @boolToInt(comparef.cmpf2(f16, comparef.GE, a, b) != .Less); +} + +fn __aeabi_fcmpgt(a: f16, b: f16) callconv(.AAPCS) i32 { + return @boolToInt(comparef.cmpf2(f16, comparef.LE, a, b) == .Greater); +} diff --git a/lib/compiler_rt/mulf3.zig b/lib/compiler_rt/mulf3.zig index 770721cb80..b02bd81671 100644 --- a/lib/compiler_rt/mulf3.zig +++ b/lib/compiler_rt/mulf3.zig @@ -32,8 +32,9 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T { const infRep = @bitCast(Z, math.inf(T)); const minNormalRep = @bitCast(Z, math.floatMin(T)); - const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent); - const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent); + const ZExp = if (typeWidth >= 32) u32 else Z; + const aExponent = @truncate(ZExp, (@bitCast(Z, a) >> significandBits) & maxExponent); + const bExponent = @truncate(ZExp, (@bitCast(Z, b) >> significandBits) & maxExponent); const productSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit; var aSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, a) & significandMask); diff --git a/lib/compiler_rt/mulhf3.zig b/lib/compiler_rt/mulhf3.zig new file mode 100644 index 0000000000..45251548be --- /dev/null +++ b/lib/compiler_rt/mulhf3.zig @@ -0,0 +1,12 @@ +const common = @import("./common.zig"); +const mulf3 = @import("./mulf3.zig").mulf3; + +pub const panic = common.panic; + +comptime { + @export(__mulhf3, .{ .name = "__mulhf3", .linkage = common.linkage }); +} + +pub fn __mulhf3(a: f16, b: f16) callconv(.C) f16 { + return mulf3(f16, a, b); +} diff --git a/lib/compiler_rt/neghf2.zig b/lib/compiler_rt/neghf2.zig new file mode 100644 index 0000000000..fe55a751d8 --- /dev/null +++ b/lib/compiler_rt/neghf2.zig @@ -0,0 +1,11 @@ +const common = @import("./common.zig"); + +pub const panic = common.panic; + +comptime { + @export(__neghf2, .{ .name = "__neghf2", .linkage = common.linkage }); +} + +fn __neghf2(a: f16) callconv(.C) f16 { + return common.fneg(a); +} diff --git a/lib/compiler_rt/subhf3.zig b/lib/compiler_rt/subhf3.zig new file mode 100644 index 0000000000..b14da2d794 --- /dev/null +++ b/lib/compiler_rt/subhf3.zig @@ -0,0 +1,12 @@ +const common = @import("./common.zig"); + +pub const panic = common.panic; + +comptime { + @export(__subhf3, .{ .name = "__subhf3", .linkage = common.linkage }); +} + +fn __subhf3(a: f16, b: f16) callconv(.C) f16 { + const neg_b = @bitCast(f16, @bitCast(u16, b) ^ (@as(u16, 1) << 15)); + return a + neg_b; +} diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 9c44e4c682..8b8f8287a3 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -24,8 +24,10 @@ comptime { @export(tanf, .{ .name = "tanf", .linkage = common.linkage }); @export(tan, .{ .name = "tan", .linkage = common.linkage }); @export(__tanx, .{ .name = "__tanx", .linkage = common.linkage }); - const tanq_sym_name = if (common.want_ppc_abi) "tanf128" else "tanq"; - @export(tanq, .{ .name = tanq_sym_name, .linkage = common.linkage }); + if (common.want_ppc_abi) { + @export(tanq, .{ .name = "tanf128", .linkage = common.linkage }); + } + @export(tanq, .{ .name = "tanq", .linkage = common.linkage }); @export(tanl, .{ .name = "tanl", .linkage = common.linkage }); } diff --git a/lib/compiler_rt/truncsfhf2.zig b/lib/compiler_rt/truncsfhf2.zig index 489fb8658d..010e257923 100644 --- a/lib/compiler_rt/truncsfhf2.zig +++ b/lib/compiler_rt/truncsfhf2.zig @@ -5,22 +5,17 @@ pub const panic = common.panic; comptime { if (common.gnu_f16_abi) { - @export(__gnu_f2h_ieee, .{ .name = "__gnu_f2h_ieee", .linkage = common.linkage }); + @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = common.linkage }); } else if (common.want_aeabi) { @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = common.linkage }); - } else { - @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = common.linkage }); } + @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = common.linkage }); } pub fn __truncsfhf2(a: f32) callconv(.C) common.F16T { return @bitCast(common.F16T, truncf(f16, f32, a)); } -fn __gnu_f2h_ieee(a: f32) callconv(.C) common.F16T { - return @bitCast(common.F16T, truncf(f16, f32, a)); -} - fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 { return @bitCast(common.F16T, truncf(f16, f32, a)); } diff --git a/lib/compiler_rt/unordhf2.zig b/lib/compiler_rt/unordhf2.zig new file mode 100644 index 0000000000..0c2aea629a --- /dev/null +++ b/lib/compiler_rt/unordhf2.zig @@ -0,0 +1,12 @@ +const common = @import("./common.zig"); +const comparef = @import("./comparef.zig"); + +pub const panic = common.panic; + +comptime { + @export(__unordhf2, .{ .name = "__unordhf2", .linkage = common.linkage }); +} + +pub fn __unordhf2(a: f16, b: f16) callconv(.C) i32 { + return comparef.unordcmp(f16, a, b); +} diff --git a/lib/compiler_rt/unordxf2.zig b/lib/compiler_rt/unordxf2.zig new file mode 100644 index 0000000000..e456096370 --- /dev/null +++ b/lib/compiler_rt/unordxf2.zig @@ -0,0 +1,12 @@ +const common = @import("./common.zig"); +const comparef = @import("./comparef.zig"); + +pub const panic = common.panic; + +comptime { + @export(__unordxf2, .{ .name = "__unordxf2", .linkage = common.linkage }); +} + +pub fn __unordxf2(a: f80, b: f80) callconv(.C) i32 { + return comparef.unordcmp(f80, a, b); +}