diff options
Diffstat (limited to 'lib/std/special/compiler_rt/ashrti3.zig')
| -rw-r--r-- | lib/std/special/compiler_rt/ashrti3.zig | 42 |
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"); +} |
