compiler-rt: Add __floatsidf & __floatsisf
Also add their AEABI aliases, __aeabi_i2f & __aeabi_i2dmaster
parent
be7cacfbbe
commit
917103710e
|
@ -677,6 +677,7 @@ set(ZIG_STD_FILES
|
|||
"special/compiler_rt/fixunstfdi.zig"
|
||||
"special/compiler_rt/fixunstfsi.zig"
|
||||
"special/compiler_rt/fixunstfti.zig"
|
||||
"special/compiler_rt/floatsiXf.zig"
|
||||
"special/compiler_rt/floattidf.zig"
|
||||
"special/compiler_rt/floattisf.zig"
|
||||
"special/compiler_rt/floattitf.zig"
|
||||
|
|
|
@ -64,6 +64,8 @@ comptime {
|
|||
@export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage);
|
||||
@export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage);
|
||||
|
||||
@export("__floatsidf", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
|
||||
@export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
|
||||
@export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage);
|
||||
@export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage);
|
||||
@export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage);
|
||||
|
@ -151,6 +153,7 @@ comptime {
|
|||
@export("__aeabi_memcmp4", __aeabi_memcmp, linkage);
|
||||
@export("__aeabi_memcmp8", __aeabi_memcmp, linkage);
|
||||
|
||||
@export("__aeabi_i2d", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
|
||||
@export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
|
||||
@export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
|
||||
|
||||
|
@ -170,6 +173,7 @@ comptime {
|
|||
@export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
|
||||
@export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
|
||||
|
||||
@export("__aeabi_i2f", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
|
||||
@export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
|
||||
@export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage);
|
||||
@export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage);
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
fn floatsiXf(comptime T: type, a: i32) T {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
const Z = @IntType(false, T.bit_count);
|
||||
const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
|
||||
|
||||
if (a == 0) {
|
||||
return T(0.0);
|
||||
}
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
const exponentBias = ((1 << exponentBits - 1) - 1);
|
||||
|
||||
const implicitBit = Z(1) << significandBits;
|
||||
const signBit = Z(1 << Z.bit_count - 1);
|
||||
|
||||
const sign = a >> 31;
|
||||
// Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).
|
||||
const abs_a = (a ^ sign) -% sign;
|
||||
// The exponent is the width of abs(a)
|
||||
const exp = Z(31 - @clz(abs_a));
|
||||
|
||||
const sign_bit = if (sign < 0) signBit else 0;
|
||||
|
||||
var mantissa: Z = undefined;
|
||||
// Shift a into the significand field and clear the implicit bit.
|
||||
if (exp <= significandBits) {
|
||||
// No rounding needed
|
||||
const shift = @intCast(S, significandBits - exp);
|
||||
mantissa = @intCast(Z, @bitCast(u32, abs_a)) << shift ^ implicitBit;
|
||||
} else {
|
||||
const shift = @intCast(S, exp - significandBits);
|
||||
// Round to the nearest number after truncation
|
||||
mantissa = @intCast(Z, @bitCast(u32, abs_a)) >> shift ^ implicitBit;
|
||||
// Align to the left and check if the truncated part is halfway over
|
||||
const round = @bitCast(u32, abs_a) << @intCast(u5, 31 - shift);
|
||||
mantissa += @boolToInt(round > 0x80000000);
|
||||
// Tie to even
|
||||
mantissa += mantissa & 1;
|
||||
}
|
||||
|
||||
// Use the addition instead of a or since we may have a carry from the
|
||||
// mantissa to the exponent
|
||||
var result = mantissa;
|
||||
result += (exp + exponentBias) << significandBits;
|
||||
result += sign_bit;
|
||||
|
||||
return @bitCast(T, result);
|
||||
}
|
||||
|
||||
pub extern fn __floatsisf(arg: i32) f32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @inlineCall(floatsiXf, f32, arg);
|
||||
}
|
||||
|
||||
pub extern fn __floatsidf(arg: i32) f64 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @inlineCall(floatsiXf, f64, arg);
|
||||
}
|
||||
|
||||
fn test_one_floatsidf(a: i32, expected: u64) void {
|
||||
const r = __floatsidf(a);
|
||||
std.testing.expect(@bitCast(u64, r) == expected);
|
||||
}
|
||||
|
||||
fn test_one_floatsisf(a: i32, expected: u32) void {
|
||||
const r = __floatsisf(a);
|
||||
std.testing.expect(@bitCast(u32, r) == expected);
|
||||
}
|
||||
|
||||
test "floatsidf" {
|
||||
test_one_floatsidf(0, 0x0000000000000000);
|
||||
test_one_floatsidf(1, 0x3ff0000000000000);
|
||||
test_one_floatsidf(-1, 0xbff0000000000000);
|
||||
test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
|
||||
test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000);
|
||||
}
|
||||
|
||||
test "floatsisf" {
|
||||
test_one_floatsisf(0, 0x00000000);
|
||||
test_one_floatsisf(1, 0x3f800000);
|
||||
test_one_floatsisf(-1, 0xbf800000);
|
||||
test_one_floatsisf(0x7FFFFFFF, 0x4f000000);
|
||||
test_one_floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000);
|
||||
}
|
Loading…
Reference in New Issue