zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

shift.zig (4845B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 const Log2Int = std.math.Log2Int;
      4 const common = @import("common.zig");
      5 
      6 pub const panic = common.panic;
      7 
      8 comptime {
      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
     31 inline 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
     53 inline 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
     76 inline 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 
     96 pub fn __ashlsi3(a: i32, b: i32) callconv(.c) i32 {
     97     return ashlXi3(i32, a, b);
     98 }
     99 
    100 pub fn __ashrsi3(a: i32, b: i32) callconv(.c) i32 {
    101     return ashrXi3(i32, a, b);
    102 }
    103 
    104 pub fn __lshrsi3(a: i32, b: i32) callconv(.c) i32 {
    105     return lshrXi3(i32, a, b);
    106 }
    107 
    108 pub fn __ashldi3(a: i64, b: i32) callconv(.c) i64 {
    109     return ashlXi3(i64, a, b);
    110 }
    111 fn __aeabi_llsl(a: i64, b: i32) callconv(.{ .arm_aapcs = .{} }) i64 {
    112     return ashlXi3(i64, a, b);
    113 }
    114 
    115 pub fn __ashlti3(a: i128, b: i32) callconv(.c) i128 {
    116     return ashlXi3(i128, a, b);
    117 }
    118 
    119 pub fn __ashrdi3(a: i64, b: i32) callconv(.c) i64 {
    120     return ashrXi3(i64, a, b);
    121 }
    122 fn __aeabi_lasr(a: i64, b: i32) callconv(.{ .arm_aapcs = .{} }) i64 {
    123     return ashrXi3(i64, a, b);
    124 }
    125 
    126 pub fn __ashrti3(a: i128, b: i32) callconv(.c) i128 {
    127     return ashrXi3(i128, a, b);
    128 }
    129 
    130 pub fn __lshrdi3(a: i64, b: i32) callconv(.c) i64 {
    131     return lshrXi3(i64, a, b);
    132 }
    133 fn __aeabi_llsr(a: i64, b: i32) callconv(.{ .arm_aapcs = .{} }) i64 {
    134     return lshrXi3(i64, a, b);
    135 }
    136 
    137 pub fn __lshrti3(a: i128, b: i32) callconv(.c) i128 {
    138     return lshrXi3(i128, a, b);
    139 }
    140 
    141 test {
    142     _ = @import("shift_test.zig");
    143 }