aboutsummaryrefslogtreecommitdiff
path: root/lib/std/special/compiler_rt/ashrti3.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/special/compiler_rt/ashrti3.zig')
-rw-r--r--lib/std/special/compiler_rt/ashrti3.zig42
1 files changed, 42 insertions, 0 deletions
diff --git a/lib/std/special/compiler_rt/ashrti3.zig b/lib/std/special/compiler_rt/ashrti3.zig
new file mode 100644
index 0000000000..40ee89c3c4
--- /dev/null
+++ b/lib/std/special/compiler_rt/ashrti3.zig
@@ -0,0 +1,42 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+
+pub extern fn __ashrti3(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 = 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 == builtin.Endian.Little)
+ struct {
+ low: i64,
+ high: i64,
+ }
+ else
+ struct {
+ high: i64,
+ low: i64,
+ };
+};
+
+test "import ashrti3" {
+ _ = @import("ashrti3_test.zig");
+}