| ... | @@ -6,10 +6,28 @@ const std = @import("std"); | ... | @@ -6,10 +6,28 @@ const std = @import("std"); |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const compiler_rt = @import("../compiler_rt.zig"); | 7 | const compiler_rt = @import("../compiler_rt.zig"); |
| 8 | | 8 | |
| | 9 | pub extern fn __addsf3(a: f32, b: f32) f32 { |
| | 10 | return addXf3(f32, a, b); |
| | 11 | } |
| | 12 | |
| | 13 | pub extern fn __adddf3(a: f64, b: f64) f64 { |
| | 14 | return addXf3(f64, a, b); |
| | 15 | } |
| | 16 | |
| 9 | pub extern fn __addtf3(a: f128, b: f128) f128 { | 17 | pub extern fn __addtf3(a: f128, b: f128) f128 { |
| 10 | return addXf3(f128, a, b); | 18 | return addXf3(f128, a, b); |
| 11 | } | 19 | } |
| 12 | | 20 | |
| | 21 | pub extern fn __subsf3(a: f32, b: f32) f32 { |
| | 22 | const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (u32(1) << 31)); |
| | 23 | return addXf3(f32, a, neg_b); |
| | 24 | } |
| | 25 | |
| | 26 | pub extern fn __subdf3(a: f64, b: f64) f64 { |
| | 27 | const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (u64(1) << 63)); |
| | 28 | return addXf3(f64, a, neg_b); |
| | 29 | } |
| | 30 | |
| 13 | pub extern fn __subtf3(a: f128, b: f128) f128 { | 31 | pub extern fn __subtf3(a: f128, b: f128) f128 { |
| 14 | const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127)); | 32 | const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127)); |
| 15 | return addXf3(f128, a, neg_b); | 33 | return addXf3(f128, a, neg_b); |
| ... | @@ -17,16 +35,18 @@ pub extern fn __subtf3(a: f128, b: f128) f128 { | ... | @@ -17,16 +35,18 @@ pub extern fn __subtf3(a: f128, b: f128) f128 { |
| 17 | | 35 | |
| 18 | inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { | 36 | inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { |
| 19 | const Z = @IntType(false, T.bit_count); | 37 | const Z = @IntType(false, T.bit_count); |
| | 38 | const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1)); |
| 20 | const significandBits = std.math.floatMantissaBits(T); | 39 | const significandBits = std.math.floatMantissaBits(T); |
| 21 | const implicitBit = Z(1) << significandBits; | 40 | const implicitBit = Z(1) << significandBits; |
| 22 | | 41 | |
| 23 | const shift = @clz(significand.*) - @clz(implicitBit); | 42 | const shift = @clz(significand.*) - @clz(implicitBit); |
| 24 | significand.* <<= @intCast(u7, shift); | 43 | significand.* <<= @intCast(S, shift); |
| 25 | return 1 - shift; | 44 | return 1 - shift; |
| 26 | } | 45 | } |
| 27 | | 46 | |
| 28 | inline fn addXf3(comptime T: type, a: T, b: T) T { | 47 | inline fn addXf3(comptime T: type, a: T, b: T) T { |
| 29 | const Z = @IntType(false, T.bit_count); | 48 | const Z = @IntType(false, T.bit_count); |
| | 49 | const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1)); |
| 30 | | 50 | |
| 31 | const typeWidth = T.bit_count; | 51 | const typeWidth = T.bit_count; |
| 32 | const significandBits = std.math.floatMantissaBits(T); | 52 | const significandBits = std.math.floatMantissaBits(T); |
| ... | @@ -126,8 +146,8 @@ inline fn addXf3(comptime T: type, a: T, b: T) T { | ... | @@ -126,8 +146,8 @@ inline fn addXf3(comptime T: type, a: T, b: T) T { |
| 126 | const @"align" = @intCast(Z, aExponent - bExponent); | 146 | const @"align" = @intCast(Z, aExponent - bExponent); |
| 127 | if (@"align" != 0) { | 147 | if (@"align" != 0) { |
| 128 | if (@"align" < typeWidth) { | 148 | if (@"align" < typeWidth) { |
| 129 | const sticky = if (bSignificand << @intCast(u7, typeWidth - @"align") != 0) Z(1) else 0; | 149 | const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) Z(1) else 0; |
| 130 | bSignificand = (bSignificand >> @truncate(u7, @"align")) | sticky; | 150 | bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky; |
| 131 | } else { | 151 | } else { |
| 132 | bSignificand = 1; // sticky; b is known to be non-zero. | 152 | bSignificand = 1; // sticky; b is known to be non-zero. |
| 133 | } | 153 | } |
| ... | @@ -141,7 +161,7 @@ inline fn addXf3(comptime T: type, a: T, b: T) T { | ... | @@ -141,7 +161,7 @@ inline fn addXf3(comptime T: type, a: T, b: T) T { |
| 141 | // and adjust the exponent: | 161 | // and adjust the exponent: |
| 142 | if (aSignificand < implicitBit << 3) { | 162 | if (aSignificand < implicitBit << 3) { |
| 143 | const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3)); | 163 | const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3)); |
| 144 | aSignificand <<= @intCast(u7, shift); | 164 | aSignificand <<= @intCast(S, shift); |
| 145 | aExponent -= shift; | 165 | aExponent -= shift; |
| 146 | } | 166 | } |
| 147 | } else { // addition | 167 | } else { // addition |
| ... | @@ -163,8 +183,8 @@ inline fn addXf3(comptime T: type, a: T, b: T) T { | ... | @@ -163,8 +183,8 @@ inline fn addXf3(comptime T: type, a: T, b: T) T { |
| 163 | // Result is denormal before rounding; the exponent is zero and we | 183 | // Result is denormal before rounding; the exponent is zero and we |
| 164 | // need to shift the significand. | 184 | // need to shift the significand. |
| 165 | const shift = @intCast(Z, 1 - aExponent); | 185 | const shift = @intCast(Z, 1 - aExponent); |
| 166 | const sticky = if (aSignificand << @intCast(u7, typeWidth - shift) != 0) Z(1) else 0; | 186 | const sticky = if (aSignificand << @intCast(S, typeWidth - shift) != 0) Z(1) else 0; |
| 167 | aSignificand = aSignificand >> @intCast(u7, shift | sticky); | 187 | aSignificand = aSignificand >> @intCast(S, shift | sticky); |
| 168 | aExponent = 0; | 188 | aExponent = 0; |
| 169 | } | 189 | } |
| 170 | | 190 | |