diff options
| author | LemonBoy <thatlemon@gmail.com> | 2020-03-30 11:55:21 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-03-30 10:58:47 -0400 |
| commit | 1ef6f068f57d1e0075c695149494420a4e387c7e (patch) | |
| tree | 8d708e589e3cd387103f4483e033147c52fb3044 /lib/std/special | |
| parent | 9bc8a1e1d0a032e2666e2a5420211cc4b052de56 (diff) | |
| download | zig-1ef6f068f57d1e0075c695149494420a4e387c7e.tar.gz zig-1ef6f068f57d1e0075c695149494420a4e387c7e.zip | |
compiler-rt: Implement all the shift builtins
* Unify all the code paths with a generic function
* Add some EABI aliases
Closes #4853
Diffstat (limited to 'lib/std/special')
| -rw-r--r-- | lib/std/special/compiler_rt.zig | 13 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/ashldi3_test.zig | 32 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/ashlti3.zig | 41 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/ashlti3_test.zig | 4 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/ashrdi3_test.zig | 55 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/ashrti3.zig | 42 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/ashrti3_test.zig | 6 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/lshrdi3_test.zig | 55 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/lshrti3.zig | 41 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/lshrti3_test.zig | 4 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/shift.zig | 130 |
11 files changed, 288 insertions, 135 deletions
diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index f0cf85a7a9..1f68d928c2 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -69,9 +69,12 @@ comptime { @export(@import("compiler_rt/divdf3.zig").__divdf3, .{ .name = "__divdf3", .linkage = linkage }); @export(@import("compiler_rt/divtf3.zig").__divtf3, .{ .name = "__divtf3", .linkage = linkage }); - @export(@import("compiler_rt/ashlti3.zig").__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); - @export(@import("compiler_rt/lshrti3.zig").__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); - @export(@import("compiler_rt/ashrti3.zig").__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__ashldi3, .{ .name = "__ashldi3", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); @export(@import("compiler_rt/floatsiXf.zig").__floatsidf, .{ .name = "__floatsidf", .linkage = linkage }); @export(@import("compiler_rt/floatsiXf.zig").__floatsisf, .{ .name = "__floatsisf", .linkage = linkage }); @@ -229,6 +232,10 @@ comptime { @export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); @export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage }); + @export(@import("compiler_rt/shift.zig").__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); diff --git a/lib/std/special/compiler_rt/ashldi3_test.zig b/lib/std/special/compiler_rt/ashldi3_test.zig new file mode 100644 index 0000000000..547c315b24 --- /dev/null +++ b/lib/std/special/compiler_rt/ashldi3_test.zig @@ -0,0 +1,32 @@ +const __ashldi3 = @import("shift.zig").__ashldi3; +const testing = @import("std").testing; + +fn test__ashldi3(a: i64, b: i32, expected: u64) void { + const x = __ashldi3(a, b); + testing.expectEqual(@bitCast(i64, expected), x); +} + +test "ashldi3" { + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x2468ACF13579BDE); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37BC); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x91A2B3C4D5E6F78); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDEF0); + + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x789ABCDEF0000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0xF13579BDE0000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0xE26AF37BC0000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0xC4D5E6F780000000); + + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x89ABCDEF00000000); + + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x13579BDE00000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x26AF37BC00000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x4D5E6F7800000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x9ABCDEF000000000); + + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0xF000000000000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0xE000000000000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0xC000000000000000); + test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0x8000000000000000); +} diff --git a/lib/std/special/compiler_rt/ashlti3.zig b/lib/std/special/compiler_rt/ashlti3.zig deleted file mode 100644 index e3bc60bbb9..0000000000 --- a/lib/std/special/compiler_rt/ashlti3.zig +++ /dev/null @@ -1,41 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); - -pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 { - var input = twords{ .all = a }; - var result: twords = undefined; - - if (b > 63) { - // 64 <= b < 128 - result.s.low = 0; - result.s.high = input.s.low << @intCast(u6, b - 64); - } else { - // 0 <= b < 64 - if (b == 0) return a; - result.s.low = input.s.low << @intCast(u6, b); - result.s.high = input.s.low >> @intCast(u6, 64 - b); - result.s.high |= input.s.high << @intCast(u6, b); - } - - return result.all; -} - -const twords = extern union { - all: i128, - s: S, - - const S = if (builtin.endian == .Little) - struct { - low: u64, - high: u64, - } - else - struct { - high: u64, - low: u64, - }; -}; - -test "import ashlti3" { - _ = @import("ashlti3_test.zig"); -} diff --git a/lib/std/special/compiler_rt/ashlti3_test.zig b/lib/std/special/compiler_rt/ashlti3_test.zig index 4ba21c138e..a4510f52d7 100644 --- a/lib/std/special/compiler_rt/ashlti3_test.zig +++ b/lib/std/special/compiler_rt/ashlti3_test.zig @@ -1,9 +1,9 @@ -const __ashlti3 = @import("ashlti3.zig").__ashlti3; +const __ashlti3 = @import("shift.zig").__ashlti3; const testing = @import("std").testing; fn test__ashlti3(a: i128, b: i32, expected: i128) void { const x = __ashlti3(a, b); - testing.expect(x == expected); + testing.expectEqual(expected, x); } test "ashlti3" { diff --git a/lib/std/special/compiler_rt/ashrdi3_test.zig b/lib/std/special/compiler_rt/ashrdi3_test.zig new file mode 100644 index 0000000000..3ba30edbfe --- /dev/null +++ b/lib/std/special/compiler_rt/ashrdi3_test.zig @@ -0,0 +1,55 @@ +const __ashrdi3 = @import("shift.zig").__ashrdi3; +const testing = @import("std").testing; + +fn test__ashrdi3(a: i64, b: i32, expected: u64) void { + const x = __ashrdi3(a, b); + testing.expectEqual(@bitCast(i64, expected), x); +} + +test "ashrdi3" { + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x91A2B3C4D5E6F7); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37B); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x2468ACF13579BD); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDE); + + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x12345678); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0x91A2B3C); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0x48D159E); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0x2468ACF); + + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x1234567); + + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x91A2B3); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x48D159); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x2468AC); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x123456); + + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0); + test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0); + + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 0, 0xFEDCBA9876543210); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 1, 0xFF6E5D4C3B2A1908); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 2, 0xFFB72EA61D950C84); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 3, 0xFFDB97530ECA8642); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 4, 0xFFEDCBA987654321); + + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 28, 0xFFFFFFFFEDCBA987); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 29, 0xFFFFFFFFF6E5D4C3); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 30, 0xFFFFFFFFFB72EA61); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 31, 0xFFFFFFFFFDB97530); + + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 32, 0xFFFFFFFFFEDCBA98); + + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 33, 0xFFFFFFFFFF6E5D4C); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 34, 0xFFFFFFFFFFB72EA6); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 35, 0xFFFFFFFFFFDB9753); + test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 36, 0xFFFFFFFFFFEDCBA9); + + test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 60, 0xFFFFFFFFFFFFFFFA); + test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 61, 0xFFFFFFFFFFFFFFFD); + test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 62, 0xFFFFFFFFFFFFFFFE); + test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 63, 0xFFFFFFFFFFFFFFFF); +} diff --git a/lib/std/special/compiler_rt/ashrti3.zig b/lib/std/special/compiler_rt/ashrti3.zig deleted file mode 100644 index 1cbe24fdeb..0000000000 --- a/lib/std/special/compiler_rt/ashrti3.zig +++ /dev/null @@ -1,42 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); - -pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 { - var input = twords{ .all = a }; - var result: twords = undefined; - - if (b > 63) { - // 64 <= b < 128 - result.s.low = input.s.high >> @intCast(u6, b - 64); - result.s.high = input.s.high >> 63; - } else { - // 0 <= b < 64 - if (b == 0) return a; - result.s.low = input.s.high << @intCast(u6, 64 - b); - // Avoid sign-extension here - result.s.low |= @bitCast(i64, @bitCast(u64, input.s.low) >> @intCast(u6, b)); - result.s.high = input.s.high >> @intCast(u6, b); - } - - return result.all; -} - -const twords = extern union { - all: i128, - s: S, - - const S = if (builtin.endian == .Little) - struct { - low: i64, - high: i64, - } - else - struct { - high: i64, - low: i64, - }; -}; - -test "import ashrti3" { - _ = @import("ashrti3_test.zig"); -} diff --git a/lib/std/special/compiler_rt/ashrti3_test.zig b/lib/std/special/compiler_rt/ashrti3_test.zig index 6a7565e557..43d5d11910 100644 --- a/lib/std/special/compiler_rt/ashrti3_test.zig +++ b/lib/std/special/compiler_rt/ashrti3_test.zig @@ -1,11 +1,9 @@ -const __ashrti3 = @import("ashrti3.zig").__ashrti3; +const __ashrti3 = @import("shift.zig").__ashrti3; const testing = @import("std").testing; fn test__ashrti3(a: i128, b: i32, expected: i128) void { const x = __ashrti3(a, b); - // @import("std").debug.warn("got 0x{x}\nexp 0x{x}\n", .{@truncate(u64, - // @bitCast(u128, x) >> 64), @truncate(u64, @bitCast(u128, expected)) >> 64}); - testing.expect(x == expected); + testing.expectEqual(expected, x); } test "ashrti3" { diff --git a/lib/std/special/compiler_rt/lshrdi3_test.zig b/lib/std/special/compiler_rt/lshrdi3_test.zig new file mode 100644 index 0000000000..906d428d1e --- /dev/null +++ b/lib/std/special/compiler_rt/lshrdi3_test.zig @@ -0,0 +1,55 @@ +const __lshrdi3 = @import("shift.zig").__lshrdi3; +const testing = @import("std").testing; + +fn test__lshrdi3(a: i64, b: i32, expected: u64) void { + const x = __lshrdi3(a, b); + testing.expectEqual(@bitCast(i64, expected), x); +} + +test "lshrdi3" { + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x91A2B3C4D5E6F7); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37B); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x2468ACF13579BD); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDE); + + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x12345678); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0x91A2B3C); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0x48D159E); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0x2468ACF); + + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x1234567); + + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x91A2B3); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x48D159); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x2468AC); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x123456); + + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0); + test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0); + + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 0, 0xFEDCBA9876543210); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 1, 0x7F6E5D4C3B2A1908); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 2, 0x3FB72EA61D950C84); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 3, 0x1FDB97530ECA8642); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 4, 0xFEDCBA987654321); + + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 28, 0xFEDCBA987); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 29, 0x7F6E5D4C3); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 30, 0x3FB72EA61); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 31, 0x1FDB97530); + + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 32, 0xFEDCBA98); + + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 33, 0x7F6E5D4C); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 34, 0x3FB72EA6); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 35, 0x1FDB9753); + test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 36, 0xFEDCBA9); + + test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 60, 0xA); + test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 61, 0x5); + test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 62, 0x2); + test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 63, 0x1); +} diff --git a/lib/std/special/compiler_rt/lshrti3.zig b/lib/std/special/compiler_rt/lshrti3.zig deleted file mode 100644 index e1c2bb5bd3..0000000000 --- a/lib/std/special/compiler_rt/lshrti3.zig +++ /dev/null @@ -1,41 +0,0 @@ -const builtin = @import("builtin"); -const compiler_rt = @import("../compiler_rt.zig"); - -pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { - var input = twords{ .all = a }; - var result: twords = undefined; - - if (b > 63) { - // 64 <= b < 128 - result.s.low = input.s.high >> @intCast(u6, b - 64); - result.s.high = 0; - } else { - // 0 <= b < 64 - if (b == 0) return a; - result.s.low = input.s.high << @intCast(u6, 64 - b); - result.s.low |= input.s.low >> @intCast(u6, b); - result.s.high = input.s.high >> @intCast(u6, b); - } - - return result.all; -} - -const twords = extern union { - all: i128, - s: S, - - const S = if (builtin.endian == .Little) - struct { - low: u64, - high: u64, - } - else - struct { - high: u64, - low: u64, - }; -}; - -test "import lshrti3" { - _ = @import("lshrti3_test.zig"); -} diff --git a/lib/std/special/compiler_rt/lshrti3_test.zig b/lib/std/special/compiler_rt/lshrti3_test.zig index 60f83d816e..c0aa191a6f 100644 --- a/lib/std/special/compiler_rt/lshrti3_test.zig +++ b/lib/std/special/compiler_rt/lshrti3_test.zig @@ -1,9 +1,9 @@ -const __lshrti3 = @import("lshrti3.zig").__lshrti3; +const __lshrti3 = @import("shift.zig").__lshrti3; const testing = @import("std").testing; fn test__lshrti3(a: i128, b: i32, expected: i128) void { const x = __lshrti3(a, b); - testing.expect(x == expected); + testing.expectEqual(expected, x); } test "lshrti3" { diff --git a/lib/std/special/compiler_rt/shift.zig b/lib/std/special/compiler_rt/shift.zig new file mode 100644 index 0000000000..e21042e14e --- /dev/null +++ b/lib/std/special/compiler_rt/shift.zig @@ -0,0 +1,130 @@ +const std = @import("std"); +const builtin = std.builtin; +const Log2Int = std.math.Log2Int; + +fn Dwords(comptime T: type, comptime signed_half: bool) type { + return extern union { + pub const HalfTU = std.meta.IntType(false, @divExact(T.bit_count, 2)); + pub const HalfTS = std.meta.IntType(true, @divExact(T.bit_count, 2)); + pub const HalfT = if (signed_half) HalfTS else HalfTU; + + all: T, + s: if (builtin.endian == .Little) + struct { low: HalfT, high: HalfT } + else + struct { high: HalfT, low: HalfT }, + }; +} + +// Arithmetic shift left +// Precondition: 0 <= b < bits_in_dword +pub fn ashlXi3(comptime T: type, a: T, b: i32) T { + const dwords = Dwords(T, false); + const S = Log2Int(dwords.HalfT); + + const input = dwords{ .all = a }; + var output: dwords = undefined; + + if (b >= dwords.HalfT.bit_count) { + output.s.low = 0; + output.s.high = input.s.low << @intCast(S, b - dwords.HalfT.bit_count); + } else if (b == 0) { + return a; + } else { + output.s.low = input.s.low << @intCast(S, b); + output.s.high = input.s.high << @intCast(S, b); + output.s.high |= input.s.low >> @intCast(S, dwords.HalfT.bit_count - b); + } + + return output.all; +} + +// Arithmetic shift right +// Precondition: 0 <= b < T.bit_count +pub fn ashrXi3(comptime T: type, a: T, b: i32) T { + const dwords = Dwords(T, true); + const S = Log2Int(dwords.HalfT); + + const input = dwords{ .all = a }; + var output: dwords = undefined; + + if (b >= dwords.HalfT.bit_count) { + output.s.high = input.s.high >> (dwords.HalfT.bit_count - 1); + output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count); + } else if (b == 0) { + return a; + } else { + output.s.high = input.s.high >> @intCast(S, b); + output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b); + // Avoid sign-extension here + output.s.low |= @bitCast( + dwords.HalfT, + @bitCast(dwords.HalfTU, input.s.low) >> @intCast(S, b), + ); + } + + return output.all; +} + +// Logical shift right +// Precondition: 0 <= b < T.bit_count +pub fn lshrXi3(comptime T: type, a: T, b: i32) T { + const dwords = Dwords(T, false); + const S = Log2Int(dwords.HalfT); + + const input = dwords{ .all = a }; + var output: dwords = undefined; + + if (b >= dwords.HalfT.bit_count) { + output.s.high = 0; + output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count); + } else if (b == 0) { + return a; + } else { + output.s.high = input.s.high >> @intCast(S, b); + output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b); + output.s.low |= input.s.low >> @intCast(S, b); + } + + return output.all; +} + +pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 { + return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i64, a, b }); +} +pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 { + return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i128, a, b }); +} +pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 { + return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i64, a, b }); +} +pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 { + return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i128, a, b }); +} +pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 { + return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i64, a, b }); +} +pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { + return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i128, a, b }); +} + +pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 { + return __ashldi3(a, b); +} +pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 { + return __ashrdi3(a, b); +} +pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 { + return __lshrdi3(a, b); +} + +test "" { + _ = @import("ashrdi3_test.zig"); + _ = @import("ashrti3_test.zig"); + + _ = @import("ashldi3_test.zig"); + _ = @import("ashlti3_test.zig"); + + _ = @import("lshrdi3_test.zig"); + _ = @import("lshrti3_test.zig"); +} |
