master
1const std = @import("std");
2const builtin = @import("builtin");
3const Log2Int = std.math.Log2Int;
4const common = @import("common.zig");
5
6pub const panic = common.panic;
7
8comptime {
9 // symbol compatibility with libgcc
10 @export(&__ashlsi3, .{ .name = "__ashlsi3", .linkage = common.linkage, .visibility = common.visibility });
11 @export(&__ashrsi3, .{ .name = "__ashrsi3", .linkage = common.linkage, .visibility = common.visibility });
12 @export(&__lshrsi3, .{ .name = "__lshrsi3", .linkage = common.linkage, .visibility = common.visibility });
13
14 @export(&__ashlti3, .{ .name = "__ashlti3", .linkage = common.linkage, .visibility = common.visibility });
15 @export(&__ashrti3, .{ .name = "__ashrti3", .linkage = common.linkage, .visibility = common.visibility });
16 @export(&__lshrti3, .{ .name = "__lshrti3", .linkage = common.linkage, .visibility = common.visibility });
17
18 if (common.want_aeabi) {
19 @export(&__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = common.linkage, .visibility = common.visibility });
20 @export(&__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = common.linkage, .visibility = common.visibility });
21 @export(&__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = common.linkage, .visibility = common.visibility });
22 } else {
23 @export(&__ashldi3, .{ .name = "__ashldi3", .linkage = common.linkage, .visibility = common.visibility });
24 @export(&__ashrdi3, .{ .name = "__ashrdi3", .linkage = common.linkage, .visibility = common.visibility });
25 @export(&__lshrdi3, .{ .name = "__lshrdi3", .linkage = common.linkage, .visibility = common.visibility });
26 }
27}
28
29// Arithmetic shift left: shift in 0 from right to left
30// Precondition: 0 <= b < bits_in_dword
31inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
32 const word_t = common.HalveInt(T, false);
33
34 const input = word_t{ .all = a };
35 var output: word_t = undefined;
36
37 if (b >= word_t.bits) {
38 output.s.low = 0;
39 output.s.high = input.s.low << @intCast(b - word_t.bits);
40 } else if (b == 0) {
41 return a;
42 } else {
43 output.s.low = input.s.low << @intCast(b);
44 output.s.high = input.s.high << @intCast(b);
45 output.s.high |= input.s.low >> @intCast(word_t.bits - b);
46 }
47
48 return output.all;
49}
50
51// Arithmetic shift right: shift in 1 from left to right
52// Precondition: 0 <= b < T.bit_count
53inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
54 const word_t = common.HalveInt(T, true);
55
56 const input = word_t{ .all = a };
57 var output: word_t = undefined;
58
59 if (b >= word_t.bits) {
60 output.s.high = input.s.high >> (word_t.bits - 1);
61 output.s.low = input.s.high >> @intCast(b - word_t.bits);
62 } else if (b == 0) {
63 return a;
64 } else {
65 output.s.high = input.s.high >> @intCast(b);
66 output.s.low = input.s.high << @intCast(word_t.bits - b);
67 // Avoid sign-extension here
68 output.s.low |= @bitCast(@as(word_t.HalfTU, @bitCast(input.s.low)) >> @intCast(b));
69 }
70
71 return output.all;
72}
73
74// Logical shift right: shift in 0 from left to right
75// Precondition: 0 <= b < T.bit_count
76inline fn lshrXi3(comptime T: type, a: T, b: i32) T {
77 const word_t = common.HalveInt(T, false);
78
79 const input = word_t{ .all = a };
80 var output: word_t = undefined;
81
82 if (b >= word_t.bits) {
83 output.s.high = 0;
84 output.s.low = input.s.high >> @intCast(b - word_t.bits);
85 } else if (b == 0) {
86 return a;
87 } else {
88 output.s.high = input.s.high >> @intCast(b);
89 output.s.low = input.s.high << @intCast(word_t.bits - b);
90 output.s.low |= input.s.low >> @intCast(b);
91 }
92
93 return output.all;
94}
95
96pub fn __ashlsi3(a: i32, b: i32) callconv(.c) i32 {
97 return ashlXi3(i32, a, b);
98}
99
100pub fn __ashrsi3(a: i32, b: i32) callconv(.c) i32 {
101 return ashrXi3(i32, a, b);
102}
103
104pub fn __lshrsi3(a: i32, b: i32) callconv(.c) i32 {
105 return lshrXi3(i32, a, b);
106}
107
108pub fn __ashldi3(a: i64, b: i32) callconv(.c) i64 {
109 return ashlXi3(i64, a, b);
110}
111fn __aeabi_llsl(a: i64, b: i32) callconv(.{ .arm_aapcs = .{} }) i64 {
112 return ashlXi3(i64, a, b);
113}
114
115pub fn __ashlti3(a: i128, b: i32) callconv(.c) i128 {
116 return ashlXi3(i128, a, b);
117}
118
119pub fn __ashrdi3(a: i64, b: i32) callconv(.c) i64 {
120 return ashrXi3(i64, a, b);
121}
122fn __aeabi_lasr(a: i64, b: i32) callconv(.{ .arm_aapcs = .{} }) i64 {
123 return ashrXi3(i64, a, b);
124}
125
126pub fn __ashrti3(a: i128, b: i32) callconv(.c) i128 {
127 return ashrXi3(i128, a, b);
128}
129
130pub fn __lshrdi3(a: i64, b: i32) callconv(.c) i64 {
131 return lshrXi3(i64, a, b);
132}
133fn __aeabi_llsr(a: i64, b: i32) callconv(.{ .arm_aapcs = .{} }) i64 {
134 return lshrXi3(i64, a, b);
135}
136
137pub fn __lshrti3(a: i128, b: i32) callconv(.c) i128 {
138 return lshrXi3(i128, a, b);
139}
140
141test {
142 _ = @import("shift_test.zig");
143}