aboutsummaryrefslogtreecommitdiff
path: root/std/special/compiler_rt/ashlti3.zig
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2019-05-10 12:45:01 +0200
committerLemonBoy <thatlemon@gmail.com>2019-05-10 13:26:33 +0200
commit7db2aa1c252919caf6120d890dde4ccb052dce93 (patch)
tree40c8e81b72bb897f8539104a4a77e24653111f09 /std/special/compiler_rt/ashlti3.zig
parent1c0223899cfe6c1c73f186330f6eff2cc9e78579 (diff)
downloadzig-7db2aa1c252919caf6120d890dde4ccb052dce93.tar.gz
zig-7db2aa1c252919caf6120d890dde4ccb052dce93.zip
compiler-rt: Add __ashlti3
Diffstat (limited to 'std/special/compiler_rt/ashlti3.zig')
-rw-r--r--std/special/compiler_rt/ashlti3.zig41
1 files changed, 41 insertions, 0 deletions
diff --git a/std/special/compiler_rt/ashlti3.zig b/std/special/compiler_rt/ashlti3.zig
new file mode 100644
index 0000000000..65b23f22e5
--- /dev/null
+++ b/std/special/compiler_rt/ashlti3.zig
@@ -0,0 +1,41 @@
+const builtin = @import("builtin");
+const compiler_rt = @import("../compiler_rt.zig");
+
+pub extern fn __ashlti3(a: i128, b: i32) 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 == builtin.Endian.Little)
+ struct {
+ low: u64,
+ high: u64,
+ }
+ else
+ struct {
+ high: u64,
+ low: u64,
+ };
+};
+
+test "import ashlti3" {
+ _ = @import("ashlti3_test.zig");
+}