diff --git a/CMakeLists.txt b/CMakeLists.txt index 5206a93292..c792ccabf7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,6 +446,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt.zig" "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/addXf3.zig" "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/atomics.zig" + "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/bswap.zig" "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/clear_cache.zig" "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/compareXf2.zig" "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/count0bits.zig" diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index d49157ff32..95edfee861 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -263,6 +263,12 @@ comptime { @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2; @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage }); + const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2; + @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage }); + const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2; + @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = linkage }); + const __bswapti2 = @import("compiler_rt/bswap.zig").__bswapti2; + @export(__bswapti2, .{ .name = "__bswapti2", .linkage = linkage }); // Integral / floating point conversion (part 1/2) const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf; diff --git a/lib/std/special/compiler_rt/bswap.zig b/lib/std/special/compiler_rt/bswap.zig new file mode 100644 index 0000000000..d903039626 --- /dev/null +++ b/lib/std/special/compiler_rt/bswap.zig @@ -0,0 +1,78 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +// bswap - byteswap +// - bswapXi2_generic for unoptimized big and little endian +// ie for u32 +// DE AD BE EF <- little|big endian +// FE BE AD DE <- big|little endian +// ie for u32 +// ff 00 00 00 >> 3*8 (leftmost byte) +// 00 ff 00 00 >> 1*8 (2nd left byte) +// 00 00 ff 00 << 1*8 (2n right byte) +// 00 00 00 ff << 3*8 (rightmost byte) + +fn bswapXi2_generic(comptime T: type) fn (a: T) callconv(.C) T { + return struct { + fn f(a: T) callconv(.C) T { + @setRuntimeSafety(builtin.is_test); + switch (@bitSizeOf(T)) { + 32 => { + // zig fmt: off + return (((a & 0xff000000) >> 24) + | ((a & 0x00ff0000) >> 8 ) + | ((a & 0x0000ff00) << 8 ) + | ((a & 0x000000ff) << 24)); + // zig fmt: on + }, + 64 => { + // zig fmt: off + return (((a & 0xff00000000000000) >> 56) + | ((a & 0x00ff000000000000) >> 40 ) + | ((a & 0x0000ff0000000000) >> 24 ) + | ((a & 0x000000ff00000000) >> 8 ) + | ((a & 0x00000000ff000000) << 8 ) + | ((a & 0x0000000000ff0000) << 24 ) + | ((a & 0x000000000000ff00) << 40 ) + | ((a & 0x00000000000000ff) << 56)); + // zig fmt: on + }, + 128 => { + // zig fmt: off + return (((a & 0xff000000000000000000000000000000) >> 120) + | ((a & 0x00ff0000000000000000000000000000) >> 104) + | ((a & 0x0000ff00000000000000000000000000) >> 88 ) + | ((a & 0x000000ff000000000000000000000000) >> 72 ) + | ((a & 0x00000000ff0000000000000000000000) >> 56 ) + | ((a & 0x0000000000ff00000000000000000000) >> 40 ) + | ((a & 0x000000000000ff000000000000000000) >> 24 ) + | ((a & 0x00000000000000ff0000000000000000) >> 8 ) + | ((a & 0x0000000000000000ff00000000000000) << 8 ) + | ((a & 0x000000000000000000ff000000000000) << 24 ) + | ((a & 0x00000000000000000000ff0000000000) << 40 ) + | ((a & 0x0000000000000000000000ff00000000) << 56 ) + | ((a & 0x000000000000000000000000ff000000) << 72 ) + | ((a & 0x00000000000000000000000000ff0000) << 88 ) + | ((a & 0x0000000000000000000000000000ff00) << 104) + | ((a & 0x000000000000000000000000000000ff) << 120)); + // zig fmt: on + }, + else => { + unreachable; + }, + } + } + }.f; +} + +pub const __bswapsi2 = bswapXi2_generic(u32); + +pub const __bswapdi2 = bswapXi2_generic(u64); + +pub const __bswapti2 = bswapXi2_generic(u128); + +test { + _ = @import("bswapsi2_test.zig"); + _ = @import("bswapdi2_test.zig"); + _ = @import("bswapti2_test.zig"); +} diff --git a/lib/std/special/compiler_rt/bswapdi2_test.zig b/lib/std/special/compiler_rt/bswapdi2_test.zig new file mode 100644 index 0000000000..a425179920 --- /dev/null +++ b/lib/std/special/compiler_rt/bswapdi2_test.zig @@ -0,0 +1,21 @@ +const bswap = @import("bswap.zig"); +const testing = @import("std").testing; + +fn test__bswapdi2(a: u64, expected: u64) !void { + var result = bswap.__bswapdi2(a); + try testing.expectEqual(expected, result); +} + +test "bswapdi2" { + try test__bswapdi2(0x0123456789abcdef, 0xefcdab8967452301); // 0..f + try test__bswapdi2(0xefcdab8967452301, 0x0123456789abcdef); + try test__bswapdi2(0x89abcdef01234567, 0x67452301efcdab89); // 8..f0..7 + try test__bswapdi2(0x67452301efcdab89, 0x89abcdef01234567); + try test__bswapdi2(0xdeadbeefdeadbeef, 0xefbeaddeefbeadde); // deadbeefdeadbeef + try test__bswapdi2(0xefbeaddeefbeadde, 0xdeadbeefdeadbeef); + try test__bswapdi2(0xdeadfacedeadface, 0xcefaaddecefaadde); // deadfacedeadface + try test__bswapdi2(0xcefaaddecefaadde, 0xdeadfacedeadface); + try test__bswapdi2(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa); // uninitialized memory + try test__bswapdi2(0x0000000000000000, 0x0000000000000000); // 0s + try test__bswapdi2(0xffffffffffffffff, 0xffffffffffffffff); // fs +} diff --git a/lib/std/special/compiler_rt/bswapsi2_test.zig b/lib/std/special/compiler_rt/bswapsi2_test.zig new file mode 100644 index 0000000000..912d3b2819 --- /dev/null +++ b/lib/std/special/compiler_rt/bswapsi2_test.zig @@ -0,0 +1,21 @@ +const bswap = @import("bswap.zig"); +const testing = @import("std").testing; + +fn test__bswapsi2(a: u32, expected: u32) !void { + var result = bswap.__bswapsi2(a); + try testing.expectEqual(expected, result); +} + +test "bswapsi2" { + try test__bswapsi2(0x01234567, 0x67452301); // 0..7 + try test__bswapsi2(0x67452301, 0x01234567); + try test__bswapsi2(0x89abcdef, 0xefcdab89); // 8..f + try test__bswapsi2(0xefcdab89, 0x89abcdef); + try test__bswapsi2(0xdeadbeef, 0xefbeadde); // deadbeef + try test__bswapsi2(0xefbeadde, 0xdeadbeef); + try test__bswapsi2(0xdeadface, 0xcefaadde); // deadface + try test__bswapsi2(0xcefaadde, 0xdeadface); + try test__bswapsi2(0xaaaaaaaa, 0xaaaaaaaa); // uninitialized memory + try test__bswapsi2(0x00000000, 0x00000000); // 0s + try test__bswapsi2(0xffffffff, 0xffffffff); // fs +} diff --git a/lib/std/special/compiler_rt/bswapti2_test.zig b/lib/std/special/compiler_rt/bswapti2_test.zig new file mode 100644 index 0000000000..6a164a28b3 --- /dev/null +++ b/lib/std/special/compiler_rt/bswapti2_test.zig @@ -0,0 +1,21 @@ +const bswap = @import("bswap.zig"); +const testing = @import("std").testing; + +fn test__bswapti2(a: u128, expected: u128) !void { + var result = bswap.__bswapti2(a); + try testing.expectEqual(expected, result); +} + +test "bswapti2" { + try test__bswapti2(0x0123456789abcdef0123456789abcdef, 0xefcdab8967452301efcdab8967452301); // 0..f + try test__bswapti2(0xefcdab8967452301efcdab8967452301, 0x0123456789abcdef0123456789abcdef); + try test__bswapti2(0x89abcdef0123456789abcdef01234567, 0x67452301efcdab8967452301efcdab89); // 8..f0..7 + try test__bswapti2(0x67452301efcdab8967452301efcdab89, 0x89abcdef0123456789abcdef01234567); + try test__bswapti2(0xdeadbeefdeadbeefdeadbeefdeadbeef, 0xefbeaddeefbeaddeefbeaddeefbeadde); // deadbeefdeadbeef + try test__bswapti2(0xefbeaddeefbeaddeefbeaddeefbeadde, 0xdeadbeefdeadbeefdeadbeefdeadbeef); + try test__bswapti2(0xdeadfacedeadfacedeadfacedeadface, 0xcefaaddecefaaddecefaaddecefaadde); // deadfacedeadface + try test__bswapti2(0xcefaaddecefaaddecefaaddecefaadde, 0xdeadfacedeadfacedeadfacedeadface); + try test__bswapti2(0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); // uninitialized memory + try test__bswapti2(0x00000000000000000000000000000000, 0x00000000000000000000000000000000); // 0s + try test__bswapti2(0xffffffffffffffffffffffffffffffff, 0xffffffffffffffffffffffffffffffff); // fs +}