authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-30 11:55:21+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-30 10:58:47-04:00
log1ef6f068f57d1e0075c695149494420a4e387c7e
tree8d708e589e3cd387103f4483e033147c52fb3044
parent9bc8a1e1d0a032e2666e2a5420211cc4b052de56

compiler-rt: Implement all the shift builtins

* Unify all the code paths with a generic function * Add some EABI aliases Closes #4853

11 files changed, 288 insertions(+), 135 deletions(-)

lib/std/special/compiler_rt.zig+10-3
......@@ -69,9 +69,12 @@ comptime {
6969 @export(@import("compiler_rt/divdf3.zig").__divdf3, .{ .name = "__divdf3", .linkage = linkage });
7070 @export(@import("compiler_rt/divtf3.zig").__divtf3, .{ .name = "__divtf3", .linkage = linkage });
7171
72 @export(@import("compiler_rt/ashlti3.zig").__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
73 @export(@import("compiler_rt/lshrti3.zig").__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
74 @export(@import("compiler_rt/ashrti3.zig").__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
72 @export(@import("compiler_rt/shift.zig").__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
73 @export(@import("compiler_rt/shift.zig").__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
74 @export(@import("compiler_rt/shift.zig").__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
75 @export(@import("compiler_rt/shift.zig").__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
76 @export(@import("compiler_rt/shift.zig").__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
77 @export(@import("compiler_rt/shift.zig").__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
7578
7679 @export(@import("compiler_rt/floatsiXf.zig").__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });
7780 @export(@import("compiler_rt/floatsiXf.zig").__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });
......@@ -229,6 +232,10 @@ comptime {
229232 @export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage });
230233 @export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage });
231234
235 @export(@import("compiler_rt/shift.zig").__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage });
236 @export(@import("compiler_rt/shift.zig").__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage });
237 @export(@import("compiler_rt/shift.zig").__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage });
238
232239 @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
233240 @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
234241 @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
lib/std/special/compiler_rt/ashldi3_test.zig created+32
......@@ -0,0 +1,32 @@
1const __ashldi3 = @import("shift.zig").__ashldi3;
2const testing = @import("std").testing;
3
4fn test__ashldi3(a: i64, b: i32, expected: u64) void {
5 const x = __ashldi3(a, b);
6 testing.expectEqual(@bitCast(i64, expected), x);
7}
8
9test "ashldi3" {
10 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF);
11 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x2468ACF13579BDE);
12 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37BC);
13 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x91A2B3C4D5E6F78);
14 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDEF0);
15
16 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x789ABCDEF0000000);
17 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0xF13579BDE0000000);
18 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0xE26AF37BC0000000);
19 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0xC4D5E6F780000000);
20
21 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x89ABCDEF00000000);
22
23 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x13579BDE00000000);
24 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x26AF37BC00000000);
25 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x4D5E6F7800000000);
26 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x9ABCDEF000000000);
27
28 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0xF000000000000000);
29 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0xE000000000000000);
30 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0xC000000000000000);
31 test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0x8000000000000000);
32}
lib/std/special/compiler_rt/ashlti3.zig deleted-41
......@@ -1,41 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3
4pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 {
5 var input = twords{ .all = a };
6 var result: twords = undefined;
7
8 if (b > 63) {
9 // 64 <= b < 128
10 result.s.low = 0;
11 result.s.high = input.s.low << @intCast(u6, b - 64);
12 } else {
13 // 0 <= b < 64
14 if (b == 0) return a;
15 result.s.low = input.s.low << @intCast(u6, b);
16 result.s.high = input.s.low >> @intCast(u6, 64 - b);
17 result.s.high |= input.s.high << @intCast(u6, b);
18 }
19
20 return result.all;
21}
22
23const twords = extern union {
24 all: i128,
25 s: S,
26
27 const S = if (builtin.endian == .Little)
28 struct {
29 low: u64,
30 high: u64,
31 }
32 else
33 struct {
34 high: u64,
35 low: u64,
36 };
37};
38
39test "import ashlti3" {
40 _ = @import("ashlti3_test.zig");
41}
lib/std/special/compiler_rt/ashlti3_test.zig+2-2
......@@ -1,9 +1,9 @@
1const __ashlti3 = @import("ashlti3.zig").__ashlti3;
1const __ashlti3 = @import("shift.zig").__ashlti3;
22const testing = @import("std").testing;
33
44fn test__ashlti3(a: i128, b: i32, expected: i128) void {
55 const x = __ashlti3(a, b);
6 testing.expect(x == expected);
6 testing.expectEqual(expected, x);
77}
88
99test "ashlti3" {
lib/std/special/compiler_rt/ashrdi3_test.zig created+55
......@@ -0,0 +1,55 @@
1const __ashrdi3 = @import("shift.zig").__ashrdi3;
2const testing = @import("std").testing;
3
4fn test__ashrdi3(a: i64, b: i32, expected: u64) void {
5 const x = __ashrdi3(a, b);
6 testing.expectEqual(@bitCast(i64, expected), x);
7}
8
9test "ashrdi3" {
10 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF);
11 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x91A2B3C4D5E6F7);
12 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37B);
13 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x2468ACF13579BD);
14 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDE);
15
16 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x12345678);
17 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0x91A2B3C);
18 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0x48D159E);
19 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0x2468ACF);
20
21 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x1234567);
22
23 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x91A2B3);
24 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x48D159);
25 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x2468AC);
26 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x123456);
27
28 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0);
29 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0);
30 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0);
31 test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0);
32
33 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 0, 0xFEDCBA9876543210);
34 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 1, 0xFF6E5D4C3B2A1908);
35 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 2, 0xFFB72EA61D950C84);
36 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 3, 0xFFDB97530ECA8642);
37 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 4, 0xFFEDCBA987654321);
38
39 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 28, 0xFFFFFFFFEDCBA987);
40 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 29, 0xFFFFFFFFF6E5D4C3);
41 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 30, 0xFFFFFFFFFB72EA61);
42 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 31, 0xFFFFFFFFFDB97530);
43
44 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 32, 0xFFFFFFFFFEDCBA98);
45
46 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 33, 0xFFFFFFFFFF6E5D4C);
47 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 34, 0xFFFFFFFFFFB72EA6);
48 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 35, 0xFFFFFFFFFFDB9753);
49 test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 36, 0xFFFFFFFFFFEDCBA9);
50
51 test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 60, 0xFFFFFFFFFFFFFFFA);
52 test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 61, 0xFFFFFFFFFFFFFFFD);
53 test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 62, 0xFFFFFFFFFFFFFFFE);
54 test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 63, 0xFFFFFFFFFFFFFFFF);
55}
lib/std/special/compiler_rt/ashrti3.zig deleted-42
......@@ -1,42 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3
4pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 {
5 var input = twords{ .all = a };
6 var result: twords = undefined;
7
8 if (b > 63) {
9 // 64 <= b < 128
10 result.s.low = input.s.high >> @intCast(u6, b - 64);
11 result.s.high = input.s.high >> 63;
12 } else {
13 // 0 <= b < 64
14 if (b == 0) return a;
15 result.s.low = input.s.high << @intCast(u6, 64 - b);
16 // Avoid sign-extension here
17 result.s.low |= @bitCast(i64, @bitCast(u64, input.s.low) >> @intCast(u6, b));
18 result.s.high = input.s.high >> @intCast(u6, b);
19 }
20
21 return result.all;
22}
23
24const twords = extern union {
25 all: i128,
26 s: S,
27
28 const S = if (builtin.endian == .Little)
29 struct {
30 low: i64,
31 high: i64,
32 }
33 else
34 struct {
35 high: i64,
36 low: i64,
37 };
38};
39
40test "import ashrti3" {
41 _ = @import("ashrti3_test.zig");
42}
lib/std/special/compiler_rt/ashrti3_test.zig+2-4
......@@ -1,11 +1,9 @@
1const __ashrti3 = @import("ashrti3.zig").__ashrti3;
1const __ashrti3 = @import("shift.zig").__ashrti3;
22const testing = @import("std").testing;
33
44fn test__ashrti3(a: i128, b: i32, expected: i128) void {
55 const x = __ashrti3(a, b);
6 // @import("std").debug.warn("got 0x{x}\nexp 0x{x}\n", .{@truncate(u64,
7 // @bitCast(u128, x) >> 64), @truncate(u64, @bitCast(u128, expected)) >> 64});
8 testing.expect(x == expected);
6 testing.expectEqual(expected, x);
97}
108
119test "ashrti3" {
lib/std/special/compiler_rt/lshrdi3_test.zig created+55
......@@ -0,0 +1,55 @@
1const __lshrdi3 = @import("shift.zig").__lshrdi3;
2const testing = @import("std").testing;
3
4fn test__lshrdi3(a: i64, b: i32, expected: u64) void {
5 const x = __lshrdi3(a, b);
6 testing.expectEqual(@bitCast(i64, expected), x);
7}
8
9test "lshrdi3" {
10 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF);
11 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x91A2B3C4D5E6F7);
12 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37B);
13 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x2468ACF13579BD);
14 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDE);
15
16 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x12345678);
17 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0x91A2B3C);
18 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0x48D159E);
19 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0x2468ACF);
20
21 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x1234567);
22
23 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x91A2B3);
24 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x48D159);
25 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x2468AC);
26 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x123456);
27
28 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0);
29 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0);
30 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0);
31 test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0);
32
33 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 0, 0xFEDCBA9876543210);
34 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 1, 0x7F6E5D4C3B2A1908);
35 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 2, 0x3FB72EA61D950C84);
36 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 3, 0x1FDB97530ECA8642);
37 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 4, 0xFEDCBA987654321);
38
39 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 28, 0xFEDCBA987);
40 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 29, 0x7F6E5D4C3);
41 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 30, 0x3FB72EA61);
42 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 31, 0x1FDB97530);
43
44 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 32, 0xFEDCBA98);
45
46 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 33, 0x7F6E5D4C);
47 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 34, 0x3FB72EA6);
48 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 35, 0x1FDB9753);
49 test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 36, 0xFEDCBA9);
50
51 test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 60, 0xA);
52 test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 61, 0x5);
53 test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 62, 0x2);
54 test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 63, 0x1);
55}
lib/std/special/compiler_rt/lshrti3.zig deleted-41
......@@ -1,41 +0,0 @@
1const builtin = @import("builtin");
2const compiler_rt = @import("../compiler_rt.zig");
3
4pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {
5 var input = twords{ .all = a };
6 var result: twords = undefined;
7
8 if (b > 63) {
9 // 64 <= b < 128
10 result.s.low = input.s.high >> @intCast(u6, b - 64);
11 result.s.high = 0;
12 } else {
13 // 0 <= b < 64
14 if (b == 0) return a;
15 result.s.low = input.s.high << @intCast(u6, 64 - b);
16 result.s.low |= input.s.low >> @intCast(u6, b);
17 result.s.high = input.s.high >> @intCast(u6, b);
18 }
19
20 return result.all;
21}
22
23const twords = extern union {
24 all: i128,
25 s: S,
26
27 const S = if (builtin.endian == .Little)
28 struct {
29 low: u64,
30 high: u64,
31 }
32 else
33 struct {
34 high: u64,
35 low: u64,
36 };
37};
38
39test "import lshrti3" {
40 _ = @import("lshrti3_test.zig");
41}
lib/std/special/compiler_rt/lshrti3_test.zig+2-2
......@@ -1,9 +1,9 @@
1const __lshrti3 = @import("lshrti3.zig").__lshrti3;
1const __lshrti3 = @import("shift.zig").__lshrti3;
22const testing = @import("std").testing;
33
44fn test__lshrti3(a: i128, b: i32, expected: i128) void {
55 const x = __lshrti3(a, b);
6 testing.expect(x == expected);
6 testing.expectEqual(expected, x);
77}
88
99test "lshrti3" {
lib/std/special/compiler_rt/shift.zig created+130
......@@ -0,0 +1,130 @@
1const std = @import("std");
2const builtin = std.builtin;
3const Log2Int = std.math.Log2Int;
4
5fn Dwords(comptime T: type, comptime signed_half: bool) type {
6 return extern union {
7 pub const HalfTU = std.meta.IntType(false, @divExact(T.bit_count, 2));
8 pub const HalfTS = std.meta.IntType(true, @divExact(T.bit_count, 2));
9 pub const HalfT = if (signed_half) HalfTS else HalfTU;
10
11 all: T,
12 s: if (builtin.endian == .Little)
13 struct { low: HalfT, high: HalfT }
14 else
15 struct { high: HalfT, low: HalfT },
16 };
17}
18
19// Arithmetic shift left
20// Precondition: 0 <= b < bits_in_dword
21pub fn ashlXi3(comptime T: type, a: T, b: i32) T {
22 const dwords = Dwords(T, false);
23 const S = Log2Int(dwords.HalfT);
24
25 const input = dwords{ .all = a };
26 var output: dwords = undefined;
27
28 if (b >= dwords.HalfT.bit_count) {
29 output.s.low = 0;
30 output.s.high = input.s.low << @intCast(S, b - dwords.HalfT.bit_count);
31 } else if (b == 0) {
32 return a;
33 } else {
34 output.s.low = input.s.low << @intCast(S, b);
35 output.s.high = input.s.high << @intCast(S, b);
36 output.s.high |= input.s.low >> @intCast(S, dwords.HalfT.bit_count - b);
37 }
38
39 return output.all;
40}
41
42// Arithmetic shift right
43// Precondition: 0 <= b < T.bit_count
44pub fn ashrXi3(comptime T: type, a: T, b: i32) T {
45 const dwords = Dwords(T, true);
46 const S = Log2Int(dwords.HalfT);
47
48 const input = dwords{ .all = a };
49 var output: dwords = undefined;
50
51 if (b >= dwords.HalfT.bit_count) {
52 output.s.high = input.s.high >> (dwords.HalfT.bit_count - 1);
53 output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count);
54 } else if (b == 0) {
55 return a;
56 } else {
57 output.s.high = input.s.high >> @intCast(S, b);
58 output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b);
59 // Avoid sign-extension here
60 output.s.low |= @bitCast(
61 dwords.HalfT,
62 @bitCast(dwords.HalfTU, input.s.low) >> @intCast(S, b),
63 );
64 }
65
66 return output.all;
67}
68
69// Logical shift right
70// Precondition: 0 <= b < T.bit_count
71pub fn lshrXi3(comptime T: type, a: T, b: i32) T {
72 const dwords = Dwords(T, false);
73 const S = Log2Int(dwords.HalfT);
74
75 const input = dwords{ .all = a };
76 var output: dwords = undefined;
77
78 if (b >= dwords.HalfT.bit_count) {
79 output.s.high = 0;
80 output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count);
81 } else if (b == 0) {
82 return a;
83 } else {
84 output.s.high = input.s.high >> @intCast(S, b);
85 output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b);
86 output.s.low |= input.s.low >> @intCast(S, b);
87 }
88
89 return output.all;
90}
91
92pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 {
93 return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i64, a, b });
94}
95pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 {
96 return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i128, a, b });
97}
98pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 {
99 return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i64, a, b });
100}
101pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 {
102 return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i128, a, b });
103}
104pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 {
105 return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i64, a, b });
106}
107pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {
108 return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i128, a, b });
109}
110
111pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {
112 return __ashldi3(a, b);
113}
114pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {
115 return __ashrdi3(a, b);
116}
117pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {
118 return __lshrdi3(a, b);
119}
120
121test "" {
122 _ = @import("ashrdi3_test.zig");
123 _ = @import("ashrti3_test.zig");
124
125 _ = @import("ashldi3_test.zig");
126 _ = @import("ashlti3_test.zig");
127
128 _ = @import("lshrdi3_test.zig");
129 _ = @import("lshrti3_test.zig");
130}