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.
This commit is contained in:
Cody Tapscott 2022-10-07 10:19:08 -07:00
parent aedafb20cf
commit 0d533433e2
15 changed files with 203 additions and 25 deletions

View file

@ -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");

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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));
}

View file

@ -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));
}

31
lib/compiler_rt/gehf2.zig Normal file
View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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 });
}

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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);
}