authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-05-08 22:26:54+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-05-08 22:26:54+02:00
log917103710e6f2a6c5a28a3630e25f59a46e3cd21
tree2f2ef2b582675aeeca66acbeaad4e85578bb865a
parentbe7cacfbbec8aed234a0316d11a9ae0e8cda0286

compiler-rt: Add __floatsidf & __floatsisf

Also add their AEABI aliases, __aeabi_i2f & __aeabi_i2d

3 files changed, 95 insertions(+), 0 deletions(-)

CMakeLists.txt+1
......@@ -677,6 +677,7 @@ set(ZIG_STD_FILES
677677 "special/compiler_rt/fixunstfdi.zig"
678678 "special/compiler_rt/fixunstfsi.zig"
679679 "special/compiler_rt/fixunstfti.zig"
680 "special/compiler_rt/floatsiXf.zig"
680681 "special/compiler_rt/floattidf.zig"
681682 "special/compiler_rt/floattisf.zig"
682683 "special/compiler_rt/floattitf.zig"
std/special/compiler_rt.zig+4
......@@ -64,6 +64,8 @@ comptime {
6464 @export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage);
6565 @export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage);
6666
67 @export("__floatsidf", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
68 @export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
6769 @export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage);
6870 @export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage);
6971 @export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage);
......@@ -151,6 +153,7 @@ comptime {
151153 @export("__aeabi_memcmp4", __aeabi_memcmp, linkage);
152154 @export("__aeabi_memcmp8", __aeabi_memcmp, linkage);
153155
156 @export("__aeabi_i2d", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage);
154157 @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
155158 @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
156159
......@@ -170,6 +173,7 @@ comptime {
170173 @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
171174 @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
172175
176 @export("__aeabi_i2f", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage);
173177 @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
174178 @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage);
175179 @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage);
std/special/compiler_rt/floatsiXf.zig created+90
......@@ -0,0 +1,90 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const maxInt = std.math.maxInt;
4
5fn floatsiXf(comptime T: type, a: i32) T {
6 @setRuntimeSafety(builtin.is_test);
7
8 const Z = @IntType(false, T.bit_count);
9 const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
10
11 if (a == 0) {
12 return T(0.0);
13 }
14
15 const significandBits = std.math.floatMantissaBits(T);
16 const exponentBits = std.math.floatExponentBits(T);
17 const exponentBias = ((1 << exponentBits - 1) - 1);
18
19 const implicitBit = Z(1) << significandBits;
20 const signBit = Z(1 << Z.bit_count - 1);
21
22 const sign = a >> 31;
23 // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).
24 const abs_a = (a ^ sign) -% sign;
25 // The exponent is the width of abs(a)
26 const exp = Z(31 - @clz(abs_a));
27
28 const sign_bit = if (sign < 0) signBit else 0;
29
30 var mantissa: Z = undefined;
31 // Shift a into the significand field and clear the implicit bit.
32 if (exp <= significandBits) {
33 // No rounding needed
34 const shift = @intCast(S, significandBits - exp);
35 mantissa = @intCast(Z, @bitCast(u32, abs_a)) << shift ^ implicitBit;
36 } else {
37 const shift = @intCast(S, exp - significandBits);
38 // Round to the nearest number after truncation
39 mantissa = @intCast(Z, @bitCast(u32, abs_a)) >> shift ^ implicitBit;
40 // Align to the left and check if the truncated part is halfway over
41 const round = @bitCast(u32, abs_a) << @intCast(u5, 31 - shift);
42 mantissa += @boolToInt(round > 0x80000000);
43 // Tie to even
44 mantissa += mantissa & 1;
45 }
46
47 // Use the addition instead of a or since we may have a carry from the
48 // mantissa to the exponent
49 var result = mantissa;
50 result += (exp + exponentBias) << significandBits;
51 result += sign_bit;
52
53 return @bitCast(T, result);
54}
55
56pub extern fn __floatsisf(arg: i32) f32 {
57 @setRuntimeSafety(builtin.is_test);
58 return @inlineCall(floatsiXf, f32, arg);
59}
60
61pub extern fn __floatsidf(arg: i32) f64 {
62 @setRuntimeSafety(builtin.is_test);
63 return @inlineCall(floatsiXf, f64, arg);
64}
65
66fn test_one_floatsidf(a: i32, expected: u64) void {
67 const r = __floatsidf(a);
68 std.testing.expect(@bitCast(u64, r) == expected);
69}
70
71fn test_one_floatsisf(a: i32, expected: u32) void {
72 const r = __floatsisf(a);
73 std.testing.expect(@bitCast(u32, r) == expected);
74}
75
76test "floatsidf" {
77 test_one_floatsidf(0, 0x0000000000000000);
78 test_one_floatsidf(1, 0x3ff0000000000000);
79 test_one_floatsidf(-1, 0xbff0000000000000);
80 test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000);
81 test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000);
82}
83
84test "floatsisf" {
85 test_one_floatsisf(0, 0x00000000);
86 test_one_floatsisf(1, 0x3f800000);
87 test_one_floatsisf(-1, 0xbf800000);
88 test_one_floatsisf(0x7FFFFFFF, 0x4f000000);
89 test_one_floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000);
90}