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}