aboutsummaryrefslogtreecommitdiff
path: root/lib/std/special/compiler_rt/lshrti3.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/special/compiler_rt/lshrti3.zig')
-rw-r--r--lib/std/special/compiler_rt/lshrti3.zig41
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/std/special/compiler_rt/lshrti3.zig b/lib/std/special/compiler_rt/lshrti3.zig
new file mode 100644
index 0000000000..329968ae40
--- /dev/null
+++ b/lib/std/special/compiler_rt/lshrti3.zig
@@ -0,0 +1,41 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+
+pub extern fn __lshrti3(a: i128, b: i32) 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 == builtin.Endian.Little)
+ struct {
+ low: u64,
+ high: u64,
+ }
+ else
+ struct {
+ high: u64,
+ low: u64,
+ };
+};
+
+test "import lshrti3" {
+ _ = @import("lshrti3_test.zig");
+}