| author | |
| committer | |
| log | 917103710e6f2a6c5a28a3630e25f59a46e3cd21 |
| tree | 2f2ef2b582675aeeca66acbeaad4e85578bb865a |
| parent | be7cacfbbec8aed234a0316d11a9ae0e8cda0286 |
Also add their AEABI aliases, __aeabi_i2f & __aeabi_i2d3 files changed, 95 insertions(+), 0 deletions(-)
CMakeLists.txt+1| ... | @@ -677,6 +677,7 @@ set(ZIG_STD_FILES | ... | @@ -677,6 +677,7 @@ set(ZIG_STD_FILES |
| 677 | "special/compiler_rt/fixunstfdi.zig" | 677 | "special/compiler_rt/fixunstfdi.zig" |
| 678 | "special/compiler_rt/fixunstfsi.zig" | 678 | "special/compiler_rt/fixunstfsi.zig" |
| 679 | "special/compiler_rt/fixunstfti.zig" | 679 | "special/compiler_rt/fixunstfti.zig" |
| 680 | "special/compiler_rt/floatsiXf.zig" | ||
| 680 | "special/compiler_rt/floattidf.zig" | 681 | "special/compiler_rt/floattidf.zig" |
| 681 | "special/compiler_rt/floattisf.zig" | 682 | "special/compiler_rt/floattisf.zig" |
| 682 | "special/compiler_rt/floattitf.zig" | 683 | "special/compiler_rt/floattitf.zig" |
std/special/compiler_rt.zig+4| ... | @@ -64,6 +64,8 @@ comptime { | ... | @@ -64,6 +64,8 @@ comptime { |
| 64 | @export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage); | 64 | @export("__divsf3", @import("compiler_rt/divsf3.zig").__divsf3, linkage); |
| 65 | @export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage); | 65 | @export("__divdf3", @import("compiler_rt/divdf3.zig").__divdf3, linkage); |
| 66 | 66 | ||
| 67 | @export("__floatsidf", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage); | ||
| 68 | @export("__floatsisf", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage); | ||
| 67 | @export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage); | 69 | @export("__floattitf", @import("compiler_rt/floattitf.zig").__floattitf, linkage); |
| 68 | @export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage); | 70 | @export("__floattidf", @import("compiler_rt/floattidf.zig").__floattidf, linkage); |
| 69 | @export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage); | 71 | @export("__floattisf", @import("compiler_rt/floattisf.zig").__floattisf, linkage); |
| ... | @@ -151,6 +153,7 @@ comptime { | ... | @@ -151,6 +153,7 @@ comptime { |
| 151 | @export("__aeabi_memcmp4", __aeabi_memcmp, linkage); | 153 | @export("__aeabi_memcmp4", __aeabi_memcmp, linkage); |
| 152 | @export("__aeabi_memcmp8", __aeabi_memcmp, linkage); | 154 | @export("__aeabi_memcmp8", __aeabi_memcmp, linkage); |
| 153 | 155 | ||
| 156 | @export("__aeabi_i2d", @import("compiler_rt/floatsiXf.zig").__floatsidf, linkage); | ||
| 154 | @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage); | 157 | @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage); |
| 155 | @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage); | 158 | @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage); |
| 156 | 159 | ||
| ... | @@ -170,6 +173,7 @@ comptime { | ... | @@ -170,6 +173,7 @@ comptime { |
| 170 | @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage); | 173 | @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage); |
| 171 | @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage); | 174 | @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage); |
| 172 | 175 | ||
| 176 | @export("__aeabi_i2f", @import("compiler_rt/floatsiXf.zig").__floatsisf, linkage); | ||
| 173 | @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage); | 177 | @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage); |
| 174 | @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage); | 178 | @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage); |
| 175 | @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage); | 179 | @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage); |
std/special/compiler_rt/floatsiXf.zig created+90| ... | @@ -0,0 +1,90 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const maxInt = std.math.maxInt; | ||
| 4 | |||
| 5 | fn 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 | |||
| 56 | pub extern fn __floatsisf(arg: i32) f32 { | ||
| 57 | @setRuntimeSafety(builtin.is_test); | ||
| 58 | return @inlineCall(floatsiXf, f32, arg); | ||
| 59 | } | ||
| 60 | |||
| 61 | pub extern fn __floatsidf(arg: i32) f64 { | ||
| 62 | @setRuntimeSafety(builtin.is_test); | ||
| 63 | return @inlineCall(floatsiXf, f64, arg); | ||
| 64 | } | ||
| 65 | |||
| 66 | fn test_one_floatsidf(a: i32, expected: u64) void { | ||
| 67 | const r = __floatsidf(a); | ||
| 68 | std.testing.expect(@bitCast(u64, r) == expected); | ||
| 69 | } | ||
| 70 | |||
| 71 | fn test_one_floatsisf(a: i32, expected: u32) void { | ||
| 72 | const r = __floatsisf(a); | ||
| 73 | std.testing.expect(@bitCast(u32, r) == expected); | ||
| 74 | } | ||
| 75 | |||
| 76 | test "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 | |||
| 84 | test "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 | } | ||