mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
compiler-rt: Implement all the shift builtins
* Unify all the code paths with a generic function * Add some EABI aliases Closes #4853
This commit is contained in:
parent
9bc8a1e1d0
commit
1ef6f068f5
@ -69,9 +69,12 @@ comptime {
|
||||
@export(@import("compiler_rt/divdf3.zig").__divdf3, .{ .name = "__divdf3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/divtf3.zig").__divtf3, .{ .name = "__divtf3", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/ashlti3.zig").__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/lshrti3.zig").__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/ashrti3.zig").__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/floatsiXf.zig").__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });
|
||||
@export(@import("compiler_rt/floatsiXf.zig").__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });
|
||||
@ -229,6 +232,10 @@ comptime {
|
||||
@export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage });
|
||||
@export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/shift.zig").__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage });
|
||||
@export(@import("compiler_rt/shift.zig").__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
|
||||
|
||||
32
lib/std/special/compiler_rt/ashldi3_test.zig
Normal file
32
lib/std/special/compiler_rt/ashldi3_test.zig
Normal file
@ -0,0 +1,32 @@
|
||||
const __ashldi3 = @import("shift.zig").__ashldi3;
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__ashldi3(a: i64, b: i32, expected: u64) void {
|
||||
const x = __ashldi3(a, b);
|
||||
testing.expectEqual(@bitCast(i64, expected), x);
|
||||
}
|
||||
|
||||
test "ashldi3" {
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x2468ACF13579BDE);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37BC);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x91A2B3C4D5E6F78);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDEF0);
|
||||
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x789ABCDEF0000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0xF13579BDE0000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0xE26AF37BC0000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0xC4D5E6F780000000);
|
||||
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x89ABCDEF00000000);
|
||||
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x13579BDE00000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x26AF37BC00000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x4D5E6F7800000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x9ABCDEF000000000);
|
||||
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0xF000000000000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0xE000000000000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0xC000000000000000);
|
||||
test__ashldi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0x8000000000000000);
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
const builtin = @import("builtin");
|
||||
const compiler_rt = @import("../compiler_rt.zig");
|
||||
|
||||
pub fn __ashlti3(a: i128, b: i32) callconv(.C) 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 == .Little)
|
||||
struct {
|
||||
low: u64,
|
||||
high: u64,
|
||||
}
|
||||
else
|
||||
struct {
|
||||
high: u64,
|
||||
low: u64,
|
||||
};
|
||||
};
|
||||
|
||||
test "import ashlti3" {
|
||||
_ = @import("ashlti3_test.zig");
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
const __ashlti3 = @import("ashlti3.zig").__ashlti3;
|
||||
const __ashlti3 = @import("shift.zig").__ashlti3;
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__ashlti3(a: i128, b: i32, expected: i128) void {
|
||||
const x = __ashlti3(a, b);
|
||||
testing.expect(x == expected);
|
||||
testing.expectEqual(expected, x);
|
||||
}
|
||||
|
||||
test "ashlti3" {
|
||||
|
||||
55
lib/std/special/compiler_rt/ashrdi3_test.zig
Normal file
55
lib/std/special/compiler_rt/ashrdi3_test.zig
Normal file
@ -0,0 +1,55 @@
|
||||
const __ashrdi3 = @import("shift.zig").__ashrdi3;
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__ashrdi3(a: i64, b: i32, expected: u64) void {
|
||||
const x = __ashrdi3(a, b);
|
||||
testing.expectEqual(@bitCast(i64, expected), x);
|
||||
}
|
||||
|
||||
test "ashrdi3" {
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x91A2B3C4D5E6F7);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37B);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x2468ACF13579BD);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDE);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x12345678);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0x91A2B3C);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0x48D159E);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0x2468ACF);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x1234567);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x91A2B3);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x48D159);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x2468AC);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x123456);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 0, 0xFEDCBA9876543210);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 1, 0xFF6E5D4C3B2A1908);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 2, 0xFFB72EA61D950C84);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 3, 0xFFDB97530ECA8642);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 4, 0xFFEDCBA987654321);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 28, 0xFFFFFFFFEDCBA987);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 29, 0xFFFFFFFFF6E5D4C3);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 30, 0xFFFFFFFFFB72EA61);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 31, 0xFFFFFFFFFDB97530);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 32, 0xFFFFFFFFFEDCBA98);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 33, 0xFFFFFFFFFF6E5D4C);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 34, 0xFFFFFFFFFFB72EA6);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 35, 0xFFFFFFFFFFDB9753);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 36, 0xFFFFFFFFFFEDCBA9);
|
||||
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 60, 0xFFFFFFFFFFFFFFFA);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 61, 0xFFFFFFFFFFFFFFFD);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 62, 0xFFFFFFFFFFFFFFFE);
|
||||
test__ashrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 63, 0xFFFFFFFFFFFFFFFF);
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
const builtin = @import("builtin");
|
||||
const compiler_rt = @import("../compiler_rt.zig");
|
||||
|
||||
pub fn __ashrti3(a: i128, b: i32) callconv(.C) 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 == .Little)
|
||||
struct {
|
||||
low: i64,
|
||||
high: i64,
|
||||
}
|
||||
else
|
||||
struct {
|
||||
high: i64,
|
||||
low: i64,
|
||||
};
|
||||
};
|
||||
|
||||
test "import ashrti3" {
|
||||
_ = @import("ashrti3_test.zig");
|
||||
}
|
||||
@ -1,11 +1,9 @@
|
||||
const __ashrti3 = @import("ashrti3.zig").__ashrti3;
|
||||
const __ashrti3 = @import("shift.zig").__ashrti3;
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__ashrti3(a: i128, b: i32, expected: i128) void {
|
||||
const x = __ashrti3(a, b);
|
||||
// @import("std").debug.warn("got 0x{x}\nexp 0x{x}\n", .{@truncate(u64,
|
||||
// @bitCast(u128, x) >> 64), @truncate(u64, @bitCast(u128, expected)) >> 64});
|
||||
testing.expect(x == expected);
|
||||
testing.expectEqual(expected, x);
|
||||
}
|
||||
|
||||
test "ashrti3" {
|
||||
|
||||
55
lib/std/special/compiler_rt/lshrdi3_test.zig
Normal file
55
lib/std/special/compiler_rt/lshrdi3_test.zig
Normal file
@ -0,0 +1,55 @@
|
||||
const __lshrdi3 = @import("shift.zig").__lshrdi3;
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__lshrdi3(a: i64, b: i32, expected: u64) void {
|
||||
const x = __lshrdi3(a, b);
|
||||
testing.expectEqual(@bitCast(i64, expected), x);
|
||||
}
|
||||
|
||||
test "lshrdi3" {
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 0, 0x123456789ABCDEF);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 1, 0x91A2B3C4D5E6F7);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 2, 0x48D159E26AF37B);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 3, 0x2468ACF13579BD);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 4, 0x123456789ABCDE);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 28, 0x12345678);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 29, 0x91A2B3C);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 30, 0x48D159E);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 31, 0x2468ACF);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 32, 0x1234567);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 33, 0x91A2B3);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 34, 0x48D159);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 35, 0x2468AC);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 36, 0x123456);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 60, 0);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 61, 0);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 62, 0);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0x0123456789ABCDEF)), 63, 0);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 0, 0xFEDCBA9876543210);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 1, 0x7F6E5D4C3B2A1908);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 2, 0x3FB72EA61D950C84);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 3, 0x1FDB97530ECA8642);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 4, 0xFEDCBA987654321);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 28, 0xFEDCBA987);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 29, 0x7F6E5D4C3);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 30, 0x3FB72EA61);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 31, 0x1FDB97530);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 32, 0xFEDCBA98);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 33, 0x7F6E5D4C);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 34, 0x3FB72EA6);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 35, 0x1FDB9753);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xFEDCBA9876543210)), 36, 0xFEDCBA9);
|
||||
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 60, 0xA);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 61, 0x5);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 62, 0x2);
|
||||
test__lshrdi3(@bitCast(i64, @as(u64, 0xAEDCBA9876543210)), 63, 0x1);
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
const builtin = @import("builtin");
|
||||
const compiler_rt = @import("../compiler_rt.zig");
|
||||
|
||||
pub fn __lshrti3(a: i128, b: i32) callconv(.C) 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 = 0;
|
||||
} else {
|
||||
// 0 <= b < 64
|
||||
if (b == 0) return a;
|
||||
result.s.low = input.s.high << @intCast(u6, 64 - b);
|
||||
result.s.low |= 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 == .Little)
|
||||
struct {
|
||||
low: u64,
|
||||
high: u64,
|
||||
}
|
||||
else
|
||||
struct {
|
||||
high: u64,
|
||||
low: u64,
|
||||
};
|
||||
};
|
||||
|
||||
test "import lshrti3" {
|
||||
_ = @import("lshrti3_test.zig");
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
const __lshrti3 = @import("lshrti3.zig").__lshrti3;
|
||||
const __lshrti3 = @import("shift.zig").__lshrti3;
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__lshrti3(a: i128, b: i32, expected: i128) void {
|
||||
const x = __lshrti3(a, b);
|
||||
testing.expect(x == expected);
|
||||
testing.expectEqual(expected, x);
|
||||
}
|
||||
|
||||
test "lshrti3" {
|
||||
|
||||
130
lib/std/special/compiler_rt/shift.zig
Normal file
130
lib/std/special/compiler_rt/shift.zig
Normal file
@ -0,0 +1,130 @@
|
||||
const std = @import("std");
|
||||
const builtin = std.builtin;
|
||||
const Log2Int = std.math.Log2Int;
|
||||
|
||||
fn Dwords(comptime T: type, comptime signed_half: bool) type {
|
||||
return extern union {
|
||||
pub const HalfTU = std.meta.IntType(false, @divExact(T.bit_count, 2));
|
||||
pub const HalfTS = std.meta.IntType(true, @divExact(T.bit_count, 2));
|
||||
pub const HalfT = if (signed_half) HalfTS else HalfTU;
|
||||
|
||||
all: T,
|
||||
s: if (builtin.endian == .Little)
|
||||
struct { low: HalfT, high: HalfT }
|
||||
else
|
||||
struct { high: HalfT, low: HalfT },
|
||||
};
|
||||
}
|
||||
|
||||
// Arithmetic shift left
|
||||
// Precondition: 0 <= b < bits_in_dword
|
||||
pub fn ashlXi3(comptime T: type, a: T, b: i32) T {
|
||||
const dwords = Dwords(T, false);
|
||||
const S = Log2Int(dwords.HalfT);
|
||||
|
||||
const input = dwords{ .all = a };
|
||||
var output: dwords = undefined;
|
||||
|
||||
if (b >= dwords.HalfT.bit_count) {
|
||||
output.s.low = 0;
|
||||
output.s.high = input.s.low << @intCast(S, b - dwords.HalfT.bit_count);
|
||||
} else if (b == 0) {
|
||||
return a;
|
||||
} else {
|
||||
output.s.low = input.s.low << @intCast(S, b);
|
||||
output.s.high = input.s.high << @intCast(S, b);
|
||||
output.s.high |= input.s.low >> @intCast(S, dwords.HalfT.bit_count - b);
|
||||
}
|
||||
|
||||
return output.all;
|
||||
}
|
||||
|
||||
// Arithmetic shift right
|
||||
// Precondition: 0 <= b < T.bit_count
|
||||
pub fn ashrXi3(comptime T: type, a: T, b: i32) T {
|
||||
const dwords = Dwords(T, true);
|
||||
const S = Log2Int(dwords.HalfT);
|
||||
|
||||
const input = dwords{ .all = a };
|
||||
var output: dwords = undefined;
|
||||
|
||||
if (b >= dwords.HalfT.bit_count) {
|
||||
output.s.high = input.s.high >> (dwords.HalfT.bit_count - 1);
|
||||
output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count);
|
||||
} else if (b == 0) {
|
||||
return a;
|
||||
} else {
|
||||
output.s.high = input.s.high >> @intCast(S, b);
|
||||
output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b);
|
||||
// Avoid sign-extension here
|
||||
output.s.low |= @bitCast(
|
||||
dwords.HalfT,
|
||||
@bitCast(dwords.HalfTU, input.s.low) >> @intCast(S, b),
|
||||
);
|
||||
}
|
||||
|
||||
return output.all;
|
||||
}
|
||||
|
||||
// Logical shift right
|
||||
// Precondition: 0 <= b < T.bit_count
|
||||
pub fn lshrXi3(comptime T: type, a: T, b: i32) T {
|
||||
const dwords = Dwords(T, false);
|
||||
const S = Log2Int(dwords.HalfT);
|
||||
|
||||
const input = dwords{ .all = a };
|
||||
var output: dwords = undefined;
|
||||
|
||||
if (b >= dwords.HalfT.bit_count) {
|
||||
output.s.high = 0;
|
||||
output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count);
|
||||
} else if (b == 0) {
|
||||
return a;
|
||||
} else {
|
||||
output.s.high = input.s.high >> @intCast(S, b);
|
||||
output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b);
|
||||
output.s.low |= input.s.low >> @intCast(S, b);
|
||||
}
|
||||
|
||||
return output.all;
|
||||
}
|
||||
|
||||
pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 {
|
||||
return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i64, a, b });
|
||||
}
|
||||
pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i128, a, b });
|
||||
}
|
||||
pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 {
|
||||
return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i64, a, b });
|
||||
}
|
||||
pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i128, a, b });
|
||||
}
|
||||
pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 {
|
||||
return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i64, a, b });
|
||||
}
|
||||
pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {
|
||||
return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i128, a, b });
|
||||
}
|
||||
|
||||
pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {
|
||||
return __ashldi3(a, b);
|
||||
}
|
||||
pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {
|
||||
return __ashrdi3(a, b);
|
||||
}
|
||||
pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {
|
||||
return __lshrdi3(a, b);
|
||||
}
|
||||
|
||||
test "" {
|
||||
_ = @import("ashrdi3_test.zig");
|
||||
_ = @import("ashrti3_test.zig");
|
||||
|
||||
_ = @import("ashldi3_test.zig");
|
||||
_ = @import("ashlti3_test.zig");
|
||||
|
||||
_ = @import("lshrdi3_test.zig");
|
||||
_ = @import("lshrti3_test.zig");
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user