diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-01-15 18:39:50 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-15 18:39:50 -0500 |
| commit | 8a792db2d8b0ea775cb255c31c207c513a45ff01 (patch) | |
| tree | 715943b6a0bae51670176ab0a25826cc7ee1cf08 /lib/std | |
| parent | 0ea96c11ef5eca9cfd19233b6d51b00ba33da716 (diff) | |
| parent | e8012740b90f9acf286d852755d358eb4c708ab5 (diff) | |
| download | zig-8a792db2d8b0ea775cb255c31c207c513a45ff01.tar.gz zig-8a792db2d8b0ea775cb255c31c207c513a45ff01.zip | |
Merge pull request #4187 from LemonBoy/builtin-rearrange
Some needed work on builtins
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/os/linux/arm-eabi.zig | 9 | ||||
| -rw-r--r-- | lib/std/special/c.zig | 2 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt.zig | 1413 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/arm.zig | 128 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/int.zig | 580 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/udivmoddi4.zig | 11 | ||||
| -rw-r--r-- | lib/std/special/compiler_rt/udivmoddi4_test.zig | 2 |
7 files changed, 743 insertions, 1402 deletions
diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm-eabi.zig index 2e55abd688..0fbbbc4085 100644 --- a/lib/std/os/linux/arm-eabi.zig +++ b/lib/std/os/linux/arm-eabi.zig @@ -88,15 +88,6 @@ pub fn syscall6( /// This matches the libc clone function. pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; -// LLVM calls this when the read-tp-hard feature is set to false. Currently, there is no way to pass -// that to llvm via zig, see https://github.com/ziglang/zig/issues/2883. -// LLVM expects libc to provide this function as __aeabi_read_tp, so it is exported if needed from special/c.zig. -pub fn getThreadPointer() callconv(.C) usize { - return asm volatile ("mrc p15, 0, %[ret], c13, c0, 3" - : [ret] "=r" (-> usize) - ); -} - pub fn restore() callconv(.Naked) void { return asm volatile ("svc #0" : diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 9ff794d5b5..0a911ba52b 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -32,8 +32,6 @@ comptime { @export(strlen, .{ .name = "strlen", .linkage = .Strong }); } else if (is_msvc) { @export(_fltused, .{ .name = "_fltused", .linkage = .Strong }); - } else if (builtin.arch == builtin.Arch.arm and builtin.os == .linux) { - @export(std.os.linux.getThreadPointer, .{ .name = "__aeabi_read_tp", .linkage = .Strong }); } } diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index 13caaacf01..2128883545 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -127,59 +127,57 @@ comptime { @export(@import("compiler_rt/fixtfsi.zig").__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage }); @export(@import("compiler_rt/fixtfti.zig").__fixtfti, .{ .name = "__fixtfti", .linkage = linkage }); - @export(@import("compiler_rt/udivmoddi4.zig").__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage }); @export(@import("compiler_rt/popcountdi2.zig").__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); @export(@import("compiler_rt/muldi3.zig").__muldi3, .{ .name = "__muldi3", .linkage = linkage }); - @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage }); - @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage }); - @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage }); - @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage }); - @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage }); - @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage }); - @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage }); - @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage }); - @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage }); - @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage }); - @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__divsi3, .{ .name = "__divsi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__divdi3, .{ .name = "__divdi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__udivsi3, .{ .name = "__udivsi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__udivdi3, .{ .name = "__udivdi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__modsi3, .{ .name = "__modsi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__moddi3, .{ .name = "__moddi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__umodsi3, .{ .name = "__umodsi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__umoddi3, .{ .name = "__umoddi3", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage }); @export(@import("compiler_rt/negXf2.zig").__negsf2, .{ .name = "__negsf2", .linkage = linkage }); @export(@import("compiler_rt/negXf2.zig").__negdf2, .{ .name = "__negdf2", .linkage = linkage }); if (is_arm_arch and !is_arm_64 and !is_test) { - @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = strong_linkage }); - @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); - @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = strong_linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); @export(@import("compiler_rt/muldi3.zig").__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage }); - @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage }); - @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage }); - @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage }); - @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage }); - @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage }); - @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage }); - @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage }); - @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage }); - @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage }); - @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage }); - @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage }); - @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage }); - @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage }); - @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage }); - @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage }); - @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage }); - @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); - @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); - @export(__aeabi_memcmp, .{ .name = "__aeabi_memcmp", .linkage = linkage }); - @export(__aeabi_memcmp, .{ .name = "__aeabi_memcmp4", .linkage = linkage }); - @export(__aeabi_memcmp, .{ .name = "__aeabi_memcmp8", .linkage = linkage }); + @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); @export(@import("compiler_rt/extendXfYf2.zig").__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); @export(@import("compiler_rt/floatsiXf.zig").__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); @@ -301,8 +299,6 @@ const std = @import("std"); const assert = std.debug.assert; const testing = std.testing; -const __udivmoddi4 = @import("compiler_rt/udivmoddi4.zig").__udivmoddi4; - // Avoid dragging in the runtime safety mechanisms into this .o file, // unless we're trying to test this file. pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { @@ -325,108 +321,6 @@ extern var __stack_chk_guard: usize = blk: { break :blk @bitCast(usize, buf); }; -fn __aeabi_unwind_cpp_pr0() callconv(.C) void { - unreachable; -} -fn __aeabi_unwind_cpp_pr1() callconv(.C) void { - unreachable; -} -fn __aeabi_unwind_cpp_pr2() callconv(.C) void { - unreachable; -} - -fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 { - @setRuntimeSafety(is_test); - - const d = __divdi3(a, b); - rem.* = a -% (d *% b); - return d; -} - -fn __divdi3(a: i64, b: i64) callconv(.C) i64 { - @setRuntimeSafety(is_test); - - // Set aside the sign of the quotient. - const sign = @bitCast(u64, (a ^ b) >> 63); - // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63). - const abs_a = (a ^ (a >> 63)) -% (a >> 63); - const abs_b = (b ^ (b >> 63)) -% (b >> 63); - // Unsigned division - const res = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), null); - // Apply sign of quotient to result and return. - return @bitCast(i64, (res ^ sign) -% sign); -} - -fn __moddi3(a: i64, b: i64) callconv(.C) i64 { - @setRuntimeSafety(is_test); - - // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63). - const abs_a = (a ^ (a >> 63)) -% (a >> 63); - const abs_b = (b ^ (b >> 63)) -% (b >> 63); - // Unsigned division - var r: u64 = undefined; - _ = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), &r); - // Apply the sign of the dividend and return. - return (@bitCast(i64, r) ^ (a >> 63)) -% (a >> 63); -} - -fn __udivdi3(a: u64, b: u64) callconv(.C) u64 { - @setRuntimeSafety(is_test); - return __udivmoddi4(a, b, null); -} - -fn __umoddi3(a: u64, b: u64) callconv(.C) u64 { - @setRuntimeSafety(is_test); - - var r: u64 = undefined; - _ = __udivmoddi4(a, b, &r); - return r; -} - -fn __aeabi_uidivmod(n: u32, d: u32) callconv(.C) extern struct { - q: u32, - r: u32, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_uidivmod).ReturnType = undefined; - result.q = __udivmodsi4(n, d, &result.r); - return result; -} - -fn __aeabi_uldivmod(n: u64, d: u64) callconv(.C) extern struct { - q: u64, - r: u64, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_uldivmod).ReturnType = undefined; - result.q = __udivmoddi4(n, d, &result.r); - return result; -} - -fn __aeabi_idivmod(n: i32, d: i32) callconv(.C) extern struct { - q: i32, - r: i32, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_idivmod).ReturnType = undefined; - result.q = __divmodsi4(n, d, &result.r); - return result; -} - -fn __aeabi_ldivmod(n: i64, d: i64) callconv(.C) extern struct { - q: i64, - r: i64, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_ldivmod).ReturnType = undefined; - result.q = __divmoddi4(n, d, &result.r); - return result; -} - const is_arm_64 = switch (builtin.arch) { builtin.Arch.aarch64, builtin.Arch.aarch64_be, @@ -446,1242 +340,3 @@ const is_arm_arch = switch (builtin.arch) { }; const is_arm_32 = is_arm_arch and !is_arm_64; - -const use_thumb_1 = usesThumb1(builtin.arch); - -fn usesThumb1(arch: builtin.Arch) bool { - return switch (arch) { - .arm => |sub_arch| switch (sub_arch) { - .v6m => true, - else => false, - }, - .armeb => |sub_arch| switch (sub_arch) { - .v6m => true, - else => false, - }, - .thumb => |sub_arch| switch (sub_arch) { - .v5, - .v5te, - .v4t, - .v6, - .v6m, - .v6k, - => true, - else => false, - }, - .thumbeb => |sub_arch| switch (sub_arch) { - .v5, - .v5te, - .v4t, - .v6, - .v6m, - .v6k, - => true, - else => false, - }, - else => false, - }; -} - -test "usesThumb1" { - testing.expect(usesThumb1(builtin.Arch{ .arm = .v6m })); - testing.expect(!usesThumb1(builtin.Arch{ .arm = .v5 })); - //etc. - - testing.expect(usesThumb1(builtin.Arch{ .armeb = .v6m })); - testing.expect(!usesThumb1(builtin.Arch{ .armeb = .v5 })); - //etc. - - testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5 })); - testing.expect(usesThumb1(builtin.Arch{ .thumb = .v5te })); - testing.expect(usesThumb1(builtin.Arch{ .thumb = .v4t })); - testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6 })); - testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6k })); - testing.expect(usesThumb1(builtin.Arch{ .thumb = .v6m })); - testing.expect(!usesThumb1(builtin.Arch{ .thumb = .v6t2 })); - //etc. - - testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5 })); - testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v5te })); - testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v4t })); - testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6 })); - testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6k })); - testing.expect(usesThumb1(builtin.Arch{ .thumbeb = .v6m })); - testing.expect(!usesThumb1(builtin.Arch{ .thumbeb = .v6t2 })); - //etc. - - testing.expect(!usesThumb1(builtin.Arch{ .aarch64 = .v8 })); - testing.expect(!usesThumb1(builtin.Arch{ .aarch64_be = .v8 })); - testing.expect(!usesThumb1(builtin.Arch.x86_64)); - testing.expect(!usesThumb1(builtin.Arch.riscv32)); - //etc. -} - -const use_thumb_1_pre_armv6 = usesThumb1PreArmv6(builtin.arch); - -fn usesThumb1PreArmv6(arch: builtin.Arch) bool { - return switch (arch) { - .thumb => |sub_arch| switch (sub_arch) { - .v5, .v5te, .v4t => true, - else => false, - }, - .thumbeb => |sub_arch| switch (sub_arch) { - .v5, .v5te, .v4t => true, - else => false, - }, - else => false, - }; -} - -fn __aeabi_memcpy() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - if (use_thumb_1) { - asm volatile ( - \\ push {r7, lr} - \\ bl memcpy - \\ pop {r7, pc} - ); - } else { - asm volatile ( - \\ b memcpy - ); - } - unreachable; -} - -fn __aeabi_memmove() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - if (use_thumb_1) { - asm volatile ( - \\ push {r7, lr} - \\ bl memmove - \\ pop {r7, pc} - ); - } else { - asm volatile ( - \\ b memmove - ); - } - unreachable; -} - -fn __aeabi_memset() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - if (use_thumb_1_pre_armv6) { - asm volatile ( - \\ eors r1, r2 - \\ eors r2, r1 - \\ eors r1, r2 - \\ push {r7, lr} - \\ b memset - \\ pop {r7, pc} - ); - } else if (use_thumb_1) { - asm volatile ( - \\ mov r3, r1 - \\ mov r1, r2 - \\ mov r2, r3 - \\ push {r7, lr} - \\ b memset - \\ pop {r7, pc} - ); - } else { - asm volatile ( - \\ mov r3, r1 - \\ mov r1, r2 - \\ mov r2, r3 - \\ b memset - ); - } - unreachable; -} - -fn __aeabi_memclr() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - if (use_thumb_1_pre_armv6) { - asm volatile ( - \\ adds r2, r1, #0 - \\ movs r1, #0 - \\ push {r7, lr} - \\ bl memset - \\ pop {r7, pc} - ); - } else if (use_thumb_1) { - asm volatile ( - \\ mov r2, r1 - \\ movs r1, #0 - \\ push {r7, lr} - \\ bl memset - \\ pop {r7, pc} - ); - } else { - asm volatile ( - \\ mov r2, r1 - \\ movs r1, #0 - \\ b memset - ); - } - unreachable; -} - -fn __aeabi_memcmp() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - if (use_thumb_1) { - asm volatile ( - \\ push {r7, lr} - \\ bl memcmp - \\ pop {r7, pc} - ); - } else { - asm volatile ( - \\ b memcmp - ); - } - unreachable; -} - -fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.C) i32 { - @setRuntimeSafety(is_test); - - const d = __divsi3(a, b); - rem.* = a -% (d * b); - return d; -} - -fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 { - @setRuntimeSafety(is_test); - - const d = __udivsi3(a, b); - rem.* = @bitCast(u32, @bitCast(i32, a) -% (@bitCast(i32, d) * @bitCast(i32, b))); - return d; -} - -fn __divsi3(n: i32, d: i32) callconv(.C) i32 { - @setRuntimeSafety(is_test); - - // Set aside the sign of the quotient. - const sign = @bitCast(u32, (n ^ d) >> 31); - // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). - const abs_n = (n ^ (n >> 31)) -% (n >> 31); - const abs_d = (d ^ (d >> 31)) -% (d >> 31); - // abs(a) / abs(b) - const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d); - // Apply sign of quotient to result and return. - return @bitCast(i32, (res ^ sign) -% sign); -} - -fn __udivsi3(n: u32, d: u32) callconv(.C) u32 { - @setRuntimeSafety(is_test); - - const n_uword_bits: c_uint = u32.bit_count; - // special cases - if (d == 0) return 0; // ?! - if (n == 0) return 0; - var sr = @bitCast(c_uint, @as(c_int, @clz(u32, d)) - @as(c_int, @clz(u32, n))); - // 0 <= sr <= n_uword_bits - 1 or sr large - if (sr > n_uword_bits - 1) { - // d > r - return 0; - } - if (sr == n_uword_bits - 1) { - // d == 1 - return n; - } - sr += 1; - // 1 <= sr <= n_uword_bits - 1 - // Not a special case - var q: u32 = n << @intCast(u5, n_uword_bits - sr); - var r: u32 = n >> @intCast(u5, sr); - var carry: u32 = 0; - while (sr > 0) : (sr -= 1) { - // r:q = ((r:q) << 1) | carry - r = (r << 1) | (q >> @intCast(u5, n_uword_bits - 1)); - q = (q << 1) | carry; - // carry = 0; - // if (r.all >= d.all) - // { - // r.all -= d.all; - // carry = 1; - // } - const s = @intCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1); - carry = @intCast(u32, s & 1); - r -= d & @bitCast(u32, s); - } - q = (q << 1) | carry; - return q; -} - -fn __modsi3(n: i32, d: i32) callconv(.C) i32 { - @setRuntimeSafety(is_test); - - return n -% __divsi3(n, d) *% d; -} - -fn __umodsi3(n: u32, d: u32) callconv(.C) u32 { - @setRuntimeSafety(is_test); - - return n -% __udivsi3(n, d) *% d; -} - -test "test_umoddi3" { - test_one_umoddi3(0, 1, 0); - test_one_umoddi3(2, 1, 0); - test_one_umoddi3(0x8000000000000000, 1, 0x0); - test_one_umoddi3(0x8000000000000000, 2, 0x0); - test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); -} - -fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { - const r = __umoddi3(a, b); - testing.expect(r == expected_r); -} - -test "test_udivsi3" { - const cases = [_][3]u32{ - [_]u32{ - 0x00000000, - 0x00000001, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x00000002, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x00000003, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x00000010, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x078644FA, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x0747AE14, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x00000000, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x00000001, - 0x00000001, - }, - [_]u32{ - 0x00000001, - 0x00000002, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x00000003, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x00000010, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x078644FA, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x0747AE14, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x00000001, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0x00000001, - 0x00000002, - }, - [_]u32{ - 0x00000002, - 0x00000002, - 0x00000001, - }, - [_]u32{ - 0x00000002, - 0x00000003, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0x00000010, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0x078644FA, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0x0747AE14, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x00000002, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0x00000001, - 0x00000003, - }, - [_]u32{ - 0x00000003, - 0x00000002, - 0x00000001, - }, - [_]u32{ - 0x00000003, - 0x00000003, - 0x00000001, - }, - [_]u32{ - 0x00000003, - 0x00000010, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0x078644FA, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0x0747AE14, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x00000003, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0x00000001, - 0x00000010, - }, - [_]u32{ - 0x00000010, - 0x00000002, - 0x00000008, - }, - [_]u32{ - 0x00000010, - 0x00000003, - 0x00000005, - }, - [_]u32{ - 0x00000010, - 0x00000010, - 0x00000001, - }, - [_]u32{ - 0x00000010, - 0x078644FA, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0x0747AE14, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x00000010, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x078644FA, - 0x00000001, - 0x078644FA, - }, - [_]u32{ - 0x078644FA, - 0x00000002, - 0x03C3227D, - }, - [_]u32{ - 0x078644FA, - 0x00000003, - 0x028216FE, - }, - [_]u32{ - 0x078644FA, - 0x00000010, - 0x0078644F, - }, - [_]u32{ - 0x078644FA, - 0x078644FA, - 0x00000001, - }, - [_]u32{ - 0x078644FA, - 0x0747AE14, - 0x00000001, - }, - [_]u32{ - 0x078644FA, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x078644FA, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x078644FA, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x078644FA, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x078644FA, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x0747AE14, - 0x00000001, - 0x0747AE14, - }, - [_]u32{ - 0x0747AE14, - 0x00000002, - 0x03A3D70A, - }, - [_]u32{ - 0x0747AE14, - 0x00000003, - 0x026D3A06, - }, - [_]u32{ - 0x0747AE14, - 0x00000010, - 0x00747AE1, - }, - [_]u32{ - 0x0747AE14, - 0x078644FA, - 0x00000000, - }, - [_]u32{ - 0x0747AE14, - 0x0747AE14, - 0x00000001, - }, - [_]u32{ - 0x0747AE14, - 0x7FFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x0747AE14, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x0747AE14, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x0747AE14, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x0747AE14, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x7FFFFFFF, - 0x00000001, - 0x7FFFFFFF, - }, - [_]u32{ - 0x7FFFFFFF, - 0x00000002, - 0x3FFFFFFF, - }, - [_]u32{ - 0x7FFFFFFF, - 0x00000003, - 0x2AAAAAAA, - }, - [_]u32{ - 0x7FFFFFFF, - 0x00000010, - 0x07FFFFFF, - }, - [_]u32{ - 0x7FFFFFFF, - 0x078644FA, - 0x00000011, - }, - [_]u32{ - 0x7FFFFFFF, - 0x0747AE14, - 0x00000011, - }, - [_]u32{ - 0x7FFFFFFF, - 0x7FFFFFFF, - 0x00000001, - }, - [_]u32{ - 0x7FFFFFFF, - 0x80000000, - 0x00000000, - }, - [_]u32{ - 0x7FFFFFFF, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x7FFFFFFF, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x7FFFFFFF, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0x80000000, - 0x00000001, - 0x80000000, - }, - [_]u32{ - 0x80000000, - 0x00000002, - 0x40000000, - }, - [_]u32{ - 0x80000000, - 0x00000003, - 0x2AAAAAAA, - }, - [_]u32{ - 0x80000000, - 0x00000010, - 0x08000000, - }, - [_]u32{ - 0x80000000, - 0x078644FA, - 0x00000011, - }, - [_]u32{ - 0x80000000, - 0x0747AE14, - 0x00000011, - }, - [_]u32{ - 0x80000000, - 0x7FFFFFFF, - 0x00000001, - }, - [_]u32{ - 0x80000000, - 0x80000000, - 0x00000001, - }, - [_]u32{ - 0x80000000, - 0xFFFFFFFD, - 0x00000000, - }, - [_]u32{ - 0x80000000, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0x80000000, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0xFFFFFFFD, - 0x00000001, - 0xFFFFFFFD, - }, - [_]u32{ - 0xFFFFFFFD, - 0x00000002, - 0x7FFFFFFE, - }, - [_]u32{ - 0xFFFFFFFD, - 0x00000003, - 0x55555554, - }, - [_]u32{ - 0xFFFFFFFD, - 0x00000010, - 0x0FFFFFFF, - }, - [_]u32{ - 0xFFFFFFFD, - 0x078644FA, - 0x00000022, - }, - [_]u32{ - 0xFFFFFFFD, - 0x0747AE14, - 0x00000023, - }, - [_]u32{ - 0xFFFFFFFD, - 0x7FFFFFFF, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFD, - 0x80000000, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFD, - 0xFFFFFFFD, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFD, - 0xFFFFFFFE, - 0x00000000, - }, - [_]u32{ - 0xFFFFFFFD, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0xFFFFFFFE, - 0x00000001, - 0xFFFFFFFE, - }, - [_]u32{ - 0xFFFFFFFE, - 0x00000002, - 0x7FFFFFFF, - }, - [_]u32{ - 0xFFFFFFFE, - 0x00000003, - 0x55555554, - }, - [_]u32{ - 0xFFFFFFFE, - 0x00000010, - 0x0FFFFFFF, - }, - [_]u32{ - 0xFFFFFFFE, - 0x078644FA, - 0x00000022, - }, - [_]u32{ - 0xFFFFFFFE, - 0x0747AE14, - 0x00000023, - }, - [_]u32{ - 0xFFFFFFFE, - 0x7FFFFFFF, - 0x00000002, - }, - [_]u32{ - 0xFFFFFFFE, - 0x80000000, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFE, - 0xFFFFFFFD, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFE, - 0xFFFFFFFE, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFE, - 0xFFFFFFFF, - 0x00000000, - }, - [_]u32{ - 0xFFFFFFFF, - 0x00000001, - 0xFFFFFFFF, - }, - [_]u32{ - 0xFFFFFFFF, - 0x00000002, - 0x7FFFFFFF, - }, - [_]u32{ - 0xFFFFFFFF, - 0x00000003, - 0x55555555, - }, - [_]u32{ - 0xFFFFFFFF, - 0x00000010, - 0x0FFFFFFF, - }, - [_]u32{ - 0xFFFFFFFF, - 0x078644FA, - 0x00000022, - }, - [_]u32{ - 0xFFFFFFFF, - 0x0747AE14, - 0x00000023, - }, - [_]u32{ - 0xFFFFFFFF, - 0x7FFFFFFF, - 0x00000002, - }, - [_]u32{ - 0xFFFFFFFF, - 0x80000000, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFF, - 0xFFFFFFFD, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFF, - 0xFFFFFFFE, - 0x00000001, - }, - [_]u32{ - 0xFFFFFFFF, - 0xFFFFFFFF, - 0x00000001, - }, - }; - - for (cases) |case| { - test_one_udivsi3(case[0], case[1], case[2]); - } -} - -fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { - const q: u32 = __udivsi3(a, b); - testing.expect(q == expected_q); -} - -test "test_divsi3" { - const cases = [_][3]i32{ - [_]i32{ 0, 1, 0 }, - [_]i32{ 0, -1, 0 }, - [_]i32{ 2, 1, 2 }, - [_]i32{ 2, -1, -2 }, - [_]i32{ -2, 1, -2 }, - [_]i32{ -2, -1, 2 }, - - [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 1, @bitCast(i32, @as(u32, 0x80000000)) }, - [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -1, @bitCast(i32, @as(u32, 0x80000000)) }, - [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -2, 0x40000000 }, - [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 2, @bitCast(i32, @as(u32, 0xC0000000)) }, - }; - - for (cases) |case| { - test_one_divsi3(case[0], case[1], case[2]); - } -} - -fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void { - const q: i32 = __divsi3(a, b); - testing.expect(q == expected_q); -} - -test "test_divmodsi4" { - const cases = [_][4]i32{ - [_]i32{ 0, 1, 0, 0 }, - [_]i32{ 0, -1, 0, 0 }, - [_]i32{ 2, 1, 2, 0 }, - [_]i32{ 2, -1, -2, 0 }, - [_]i32{ -2, 1, -2, 0 }, - [_]i32{ -2, -1, 2, 0 }, - [_]i32{ 7, 5, 1, 2 }, - [_]i32{ -7, 5, -1, -2 }, - [_]i32{ 19, 5, 3, 4 }, - [_]i32{ 19, -5, -3, 4 }, - - [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 8, @bitCast(i32, @as(u32, 0xf0000000)), 0 }, - [_]i32{ @bitCast(i32, @as(u32, 0x80000007)), 8, @bitCast(i32, @as(u32, 0xf0000001)), -1 }, - }; - - for (cases) |case| { - test_one_divmodsi4(case[0], case[1], case[2], case[3]); - } -} - -fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void { - var r: i32 = undefined; - const q: i32 = __divmodsi4(a, b, &r); - testing.expect(q == expected_q and r == expected_r); -} - -test "test_divdi3" { - const cases = [_][3]i64{ - [_]i64{ 0, 1, 0 }, - [_]i64{ 0, -1, 0 }, - [_]i64{ 2, 1, 2 }, - [_]i64{ 2, -1, -2 }, - [_]i64{ -2, 1, -2 }, - [_]i64{ -2, -1, 2 }, - - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, @bitCast(i64, @as(u64, 0x8000000000000000)) }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, @bitCast(i64, @as(u64, 0x8000000000000000)) }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0x4000000000000000 }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, @bitCast(i64, @as(u64, 0xC000000000000000)) }, - }; - - for (cases) |case| { - test_one_divdi3(case[0], case[1], case[2]); - } -} - -fn test_one_divdi3(a: i64, b: i64, expected_q: i64) void { - const q: i64 = __divdi3(a, b); - testing.expect(q == expected_q); -} - -test "test_moddi3" { - const cases = [_][3]i64{ - [_]i64{ 0, 1, 0 }, - [_]i64{ 0, -1, 0 }, - [_]i64{ 5, 3, 2 }, - [_]i64{ 5, -3, 2 }, - [_]i64{ -5, 3, -2 }, - [_]i64{ -5, -3, -2 }, - - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, 0 }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, 0 }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, 0 }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0 }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 3, -2 }, - [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -3, -2 }, - }; - - for (cases) |case| { - test_one_moddi3(case[0], case[1], case[2]); - } -} - -fn test_one_moddi3(a: i64, b: i64, expected_r: i64) void { - const r: i64 = __moddi3(a, b); - testing.expect(r == expected_r); -} - -test "test_modsi3" { - const cases = [_][3]i32{ - [_]i32{ 0, 1, 0 }, - [_]i32{ 0, -1, 0 }, - [_]i32{ 5, 3, 2 }, - [_]i32{ 5, -3, 2 }, - [_]i32{ -5, 3, -2 }, - [_]i32{ -5, -3, -2 }, - [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 1, 0x0 }, - [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 2, 0x0 }, - [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -2, 0x0 }, - [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 3, -2 }, - [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -3, -2 }, - }; - - for (cases) |case| { - test_one_modsi3(case[0], case[1], case[2]); - } -} - -fn test_one_modsi3(a: i32, b: i32, expected_r: i32) void { - const r: i32 = __modsi3(a, b); - testing.expect(r == expected_r); -} - -test "test_umodsi3" { - const cases = [_][3]u32{ - [_]u32{ 0x00000000, 0x00000001, 0x00000000 }, - [_]u32{ 0x00000000, 0x00000002, 0x00000000 }, - [_]u32{ 0x00000000, 0x00000003, 0x00000000 }, - [_]u32{ 0x00000000, 0x00000010, 0x00000000 }, - [_]u32{ 0x00000000, 0x078644FA, 0x00000000 }, - [_]u32{ 0x00000000, 0x0747AE14, 0x00000000 }, - [_]u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 }, - [_]u32{ 0x00000000, 0x80000000, 0x00000000 }, - [_]u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 }, - [_]u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 }, - [_]u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 }, - [_]u32{ 0x00000001, 0x00000001, 0x00000000 }, - [_]u32{ 0x00000001, 0x00000002, 0x00000001 }, - [_]u32{ 0x00000001, 0x00000003, 0x00000001 }, - [_]u32{ 0x00000001, 0x00000010, 0x00000001 }, - [_]u32{ 0x00000001, 0x078644FA, 0x00000001 }, - [_]u32{ 0x00000001, 0x0747AE14, 0x00000001 }, - [_]u32{ 0x00000001, 0x7FFFFFFF, 0x00000001 }, - [_]u32{ 0x00000001, 0x80000000, 0x00000001 }, - [_]u32{ 0x00000001, 0xFFFFFFFD, 0x00000001 }, - [_]u32{ 0x00000001, 0xFFFFFFFE, 0x00000001 }, - [_]u32{ 0x00000001, 0xFFFFFFFF, 0x00000001 }, - [_]u32{ 0x00000002, 0x00000001, 0x00000000 }, - [_]u32{ 0x00000002, 0x00000002, 0x00000000 }, - [_]u32{ 0x00000002, 0x00000003, 0x00000002 }, - [_]u32{ 0x00000002, 0x00000010, 0x00000002 }, - [_]u32{ 0x00000002, 0x078644FA, 0x00000002 }, - [_]u32{ 0x00000002, 0x0747AE14, 0x00000002 }, - [_]u32{ 0x00000002, 0x7FFFFFFF, 0x00000002 }, - [_]u32{ 0x00000002, 0x80000000, 0x00000002 }, - [_]u32{ 0x00000002, 0xFFFFFFFD, 0x00000002 }, - [_]u32{ 0x00000002, 0xFFFFFFFE, 0x00000002 }, - [_]u32{ 0x00000002, 0xFFFFFFFF, 0x00000002 }, - [_]u32{ 0x00000003, 0x00000001, 0x00000000 }, - [_]u32{ 0x00000003, 0x00000002, 0x00000001 }, - [_]u32{ 0x00000003, 0x00000003, 0x00000000 }, - [_]u32{ 0x00000003, 0x00000010, 0x00000003 }, - [_]u32{ 0x00000003, 0x078644FA, 0x00000003 }, - [_]u32{ 0x00000003, 0x0747AE14, 0x00000003 }, - [_]u32{ 0x00000003, 0x7FFFFFFF, 0x00000003 }, - [_]u32{ 0x00000003, 0x80000000, 0x00000003 }, - [_]u32{ 0x00000003, 0xFFFFFFFD, 0x00000003 }, - [_]u32{ 0x00000003, 0xFFFFFFFE, 0x00000003 }, - [_]u32{ 0x00000003, 0xFFFFFFFF, 0x00000003 }, - [_]u32{ 0x00000010, 0x00000001, 0x00000000 }, - [_]u32{ 0x00000010, 0x00000002, 0x00000000 }, - [_]u32{ 0x00000010, 0x00000003, 0x00000001 }, - [_]u32{ 0x00000010, 0x00000010, 0x00000000 }, - [_]u32{ 0x00000010, 0x078644FA, 0x00000010 }, - [_]u32{ 0x00000010, 0x0747AE14, 0x00000010 }, - [_]u32{ 0x00000010, 0x7FFFFFFF, 0x00000010 }, - [_]u32{ 0x00000010, 0x80000000, 0x00000010 }, - [_]u32{ 0x00000010, 0xFFFFFFFD, 0x00000010 }, - [_]u32{ 0x00000010, 0xFFFFFFFE, 0x00000010 }, - [_]u32{ 0x00000010, 0xFFFFFFFF, 0x00000010 }, - [_]u32{ 0x078644FA, 0x00000001, 0x00000000 }, - [_]u32{ 0x078644FA, 0x00000002, 0x00000000 }, - [_]u32{ 0x078644FA, 0x00000003, 0x00000000 }, - [_]u32{ 0x078644FA, 0x00000010, 0x0000000A }, - [_]u32{ 0x078644FA, 0x078644FA, 0x00000000 }, - [_]u32{ 0x078644FA, 0x0747AE14, 0x003E96E6 }, - [_]u32{ 0x078644FA, 0x7FFFFFFF, 0x078644FA }, - [_]u32{ 0x078644FA, 0x80000000, 0x078644FA }, - [_]u32{ 0x078644FA, 0xFFFFFFFD, 0x078644FA }, - [_]u32{ 0x078644FA, 0xFFFFFFFE, 0x078644FA }, - [_]u32{ 0x078644FA, 0xFFFFFFFF, 0x078644FA }, - [_]u32{ 0x0747AE14, 0x00000001, 0x00000000 }, - [_]u32{ 0x0747AE14, 0x00000002, 0x00000000 }, - [_]u32{ 0x0747AE14, 0x00000003, 0x00000002 }, - [_]u32{ 0x0747AE14, 0x00000010, 0x00000004 }, - [_]u32{ 0x0747AE14, 0x078644FA, 0x0747AE14 }, - [_]u32{ 0x0747AE14, 0x0747AE14, 0x00000000 }, - [_]u32{ 0x0747AE14, 0x7FFFFFFF, 0x0747AE14 }, - [_]u32{ 0x0747AE14, 0x80000000, 0x0747AE14 }, - [_]u32{ 0x0747AE14, 0xFFFFFFFD, 0x0747AE14 }, - [_]u32{ 0x0747AE14, 0xFFFFFFFE, 0x0747AE14 }, - [_]u32{ 0x0747AE14, 0xFFFFFFFF, 0x0747AE14 }, - [_]u32{ 0x7FFFFFFF, 0x00000001, 0x00000000 }, - [_]u32{ 0x7FFFFFFF, 0x00000002, 0x00000001 }, - [_]u32{ 0x7FFFFFFF, 0x00000003, 0x00000001 }, - [_]u32{ 0x7FFFFFFF, 0x00000010, 0x0000000F }, - [_]u32{ 0x7FFFFFFF, 0x078644FA, 0x00156B65 }, - [_]u32{ 0x7FFFFFFF, 0x0747AE14, 0x043D70AB }, - [_]u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000 }, - [_]u32{ 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF }, - [_]u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x7FFFFFFF }, - [_]u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x7FFFFFFF }, - [_]u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF }, - [_]u32{ 0x80000000, 0x00000001, 0x00000000 }, - [_]u32{ 0x80000000, 0x00000002, 0x00000000 }, - [_]u32{ 0x80000000, 0x00000003, 0x00000002 }, - [_]u32{ 0x80000000, 0x00000010, 0x00000000 }, - [_]u32{ 0x80000000, 0x078644FA, 0x00156B66 }, - [_]u32{ 0x80000000, 0x0747AE14, 0x043D70AC }, - [_]u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 }, - [_]u32{ 0x80000000, 0x80000000, 0x00000000 }, - [_]u32{ 0x80000000, 0xFFFFFFFD, 0x80000000 }, - [_]u32{ 0x80000000, 0xFFFFFFFE, 0x80000000 }, - [_]u32{ 0x80000000, 0xFFFFFFFF, 0x80000000 }, - [_]u32{ 0xFFFFFFFD, 0x00000001, 0x00000000 }, - [_]u32{ 0xFFFFFFFD, 0x00000002, 0x00000001 }, - [_]u32{ 0xFFFFFFFD, 0x00000003, 0x00000001 }, - [_]u32{ 0xFFFFFFFD, 0x00000010, 0x0000000D }, - [_]u32{ 0xFFFFFFFD, 0x078644FA, 0x002AD6C9 }, - [_]u32{ 0xFFFFFFFD, 0x0747AE14, 0x01333341 }, - [_]u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x7FFFFFFE }, - [_]u32{ 0xFFFFFFFD, 0x80000000, 0x7FFFFFFD }, - [_]u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000000 }, - [_]u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFD }, - [_]u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFD }, - [_]u32{ 0xFFFFFFFE, 0x00000001, 0x00000000 }, - [_]u32{ 0xFFFFFFFE, 0x00000002, 0x00000000 }, - [_]u32{ 0xFFFFFFFE, 0x00000003, 0x00000002 }, - [_]u32{ 0xFFFFFFFE, 0x00000010, 0x0000000E }, - [_]u32{ 0xFFFFFFFE, 0x078644FA, 0x002AD6CA }, - [_]u32{ 0xFFFFFFFE, 0x0747AE14, 0x01333342 }, - [_]u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000000 }, - [_]u32{ 0xFFFFFFFE, 0x80000000, 0x7FFFFFFE }, - [_]u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 }, - [_]u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000000 }, - [_]u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE }, - [_]u32{ 0xFFFFFFFF, 0x00000001, 0x00000000 }, - [_]u32{ 0xFFFFFFFF, 0x00000002, 0x00000001 }, - [_]u32{ 0xFFFFFFFF, 0x00000003, 0x00000000 }, - [_]u32{ 0xFFFFFFFF, 0x00000010, 0x0000000F }, - [_]u32{ 0xFFFFFFFF, 0x078644FA, 0x002AD6CB }, - [_]u32{ 0xFFFFFFFF, 0x0747AE14, 0x01333343 }, - [_]u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001 }, - [_]u32{ 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF }, - [_]u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000002 }, - [_]u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 }, - [_]u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, - }; - - for (cases) |case| { - test_one_umodsi3(case[0], case[1], case[2]); - } -} - -fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void { - const r: u32 = __umodsi3(a, b); - testing.expect(r == expected_r); -} diff --git a/lib/std/special/compiler_rt/arm.zig b/lib/std/special/compiler_rt/arm.zig new file mode 100644 index 0000000000..9ba423931b --- /dev/null +++ b/lib/std/special/compiler_rt/arm.zig @@ -0,0 +1,128 @@ +// ARM specific builtins +const builtin = @import("builtin"); +const is_test = builtin.is_test; + +const __divmodsi4 = @import("int.zig").__divmodsi4; +const __udivmodsi4 = @import("int.zig").__udivmodsi4; +const __divmoddi4 = @import("int.zig").__divmoddi4; +const __udivmoddi4 = @import("int.zig").__udivmoddi4; + +extern fn memset(dest: ?[*]u8, c: u8, n: usize) ?[*]u8; +extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) ?[*]u8; +extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) ?[*]u8; + +pub fn __aeabi_memcpy(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { + @setRuntimeSafety(false); + _ = memcpy(dest, src, n); +} + +pub fn __aeabi_memmove(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { + @setRuntimeSafety(false); + _ = memmove(dest, src, n); +} + +pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void { + @setRuntimeSafety(false); + // This is dentical to the standard `memset` definition but with the last + // two arguments swapped + _ = memset(dest, c, n); +} + +pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void { + @setRuntimeSafety(false); + _ = memset(dest, 0, n); +} + +pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void { + unreachable; +} +pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void { + unreachable; +} +pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void { + unreachable; +} + +// This function can only clobber r0 according to the ABI +pub fn __aeabi_read_tp() callconv(.Naked) void { + asm volatile ( + \\ mrc p15, 0, r0, c13, c0, 3 + \\ bx lr + ); + unreachable; +} + +// The following functions are wrapped in an asm block to ensure the required +// calling convention is always respected + +pub fn __aeabi_uidivmod() callconv(.Naked) void { + // Divide r0 by r1; the quotient goes in r0, the remainder in r1 + asm volatile ( + \\ push {lr} + \\ sub sp, #4 + \\ mov r2, sp + \\ bl __udivmodsi4 + \\ ldr r1, [sp] + \\ add sp, #4 + \\ pop {pc} + : + : + : "memory" + ); + unreachable; +} + +pub fn __aeabi_uldivmod() callconv(.Naked) void { + // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 + asm volatile ( + \\ push {r4, lr} + \\ sub sp, #16 + \\ add r4, sp, #8 + \\ str r4, [sp] + \\ bl __udivmoddi4 + \\ ldr r2, [sp, #8] + \\ ldr r3, [sp, #12] + \\ add sp, #16 + \\ pop {r4, pc} + : + : + : "memory" + ); + unreachable; +} + +pub fn __aeabi_idivmod() callconv(.Naked) void { + // Divide r0 by r1; the quotient goes in r0, the remainder in r1 + asm volatile ( + \\ push {lr} + \\ sub sp, #4 + \\ mov r2, sp + \\ bl __divmodsi4 + \\ ldr r1, [sp] + \\ add sp, #4 + \\ pop {pc} + : + : + : "memory" + ); + unreachable; +} + +pub fn __aeabi_ldivmod() callconv(.Naked) void { + // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 + asm volatile ( + \\ push {r4, lr} + \\ sub sp, #16 + \\ add r4, sp, #8 + \\ str r4, [sp] + \\ bl __divmoddi4 + \\ ldr r2, [sp, #8] + \\ ldr r3, [sp, #12] + \\ add sp, #16 + \\ pop {r4, pc} + : + : + : "memory" + ); + unreachable; +} diff --git a/lib/std/special/compiler_rt/int.zig b/lib/std/special/compiler_rt/int.zig new file mode 100644 index 0000000000..88f4d66966 --- /dev/null +++ b/lib/std/special/compiler_rt/int.zig @@ -0,0 +1,580 @@ +// Builtin functions that operate on integer types +const builtin = @import("builtin"); +const testing = @import("std").testing; + +const udivmod = @import("udivmod.zig").udivmod; + +pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 { + @setRuntimeSafety(builtin.is_test); + + const d = __divdi3(a, b); + rem.* = a -% (d *% b); + return d; +} + +pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 { + @setRuntimeSafety(builtin.is_test); + return udivmod(u64, a, b, maybe_rem); +} + +test "test_udivmoddi4" { + _ = @import("udivmoddi4_test.zig"); +} + +pub fn __divdi3(a: i64, b: i64) callconv(.C) i64 { + @setRuntimeSafety(builtin.is_test); + + // Set aside the sign of the quotient. + const sign = @bitCast(u64, (a ^ b) >> 63); + // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63). + const abs_a = (a ^ (a >> 63)) -% (a >> 63); + const abs_b = (b ^ (b >> 63)) -% (b >> 63); + // Unsigned division + const res = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), null); + // Apply sign of quotient to result and return. + return @bitCast(i64, (res ^ sign) -% sign); +} + +test "test_divdi3" { + const cases = [_][3]i64{ + [_]i64{ 0, 1, 0 }, + [_]i64{ 0, -1, 0 }, + [_]i64{ 2, 1, 2 }, + [_]i64{ 2, -1, -2 }, + [_]i64{ -2, 1, -2 }, + [_]i64{ -2, -1, 2 }, + + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, @bitCast(i64, @as(u64, 0x8000000000000000)) }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, @bitCast(i64, @as(u64, 0x8000000000000000)) }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0x4000000000000000 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, @bitCast(i64, @as(u64, 0xC000000000000000)) }, + }; + + for (cases) |case| { + test_one_divdi3(case[0], case[1], case[2]); + } +} + +fn test_one_divdi3(a: i64, b: i64, expected_q: i64) void { + const q: i64 = __divdi3(a, b); + testing.expect(q == expected_q); +} + +pub fn __moddi3(a: i64, b: i64) callconv(.C) i64 { + @setRuntimeSafety(builtin.is_test); + + // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63). + const abs_a = (a ^ (a >> 63)) -% (a >> 63); + const abs_b = (b ^ (b >> 63)) -% (b >> 63); + // Unsigned division + var r: u64 = undefined; + _ = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), &r); + // Apply the sign of the dividend and return. + return (@bitCast(i64, r) ^ (a >> 63)) -% (a >> 63); +} + +test "test_moddi3" { + const cases = [_][3]i64{ + [_]i64{ 0, 1, 0 }, + [_]i64{ 0, -1, 0 }, + [_]i64{ 5, 3, 2 }, + [_]i64{ 5, -3, 2 }, + [_]i64{ -5, 3, -2 }, + [_]i64{ -5, -3, -2 }, + + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 3, -2 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -3, -2 }, + }; + + for (cases) |case| { + test_one_moddi3(case[0], case[1], case[2]); + } +} + +fn test_one_moddi3(a: i64, b: i64, expected_r: i64) void { + const r: i64 = __moddi3(a, b); + testing.expect(r == expected_r); +} + +pub fn __udivdi3(a: u64, b: u64) callconv(.C) u64 { + @setRuntimeSafety(builtin.is_test); + return __udivmoddi4(a, b, null); +} + +pub fn __umoddi3(a: u64, b: u64) callconv(.C) u64 { + @setRuntimeSafety(builtin.is_test); + + var r: u64 = undefined; + _ = __udivmoddi4(a, b, &r); + return r; +} + +test "test_umoddi3" { + test_one_umoddi3(0, 1, 0); + test_one_umoddi3(2, 1, 0); + test_one_umoddi3(0x8000000000000000, 1, 0x0); + test_one_umoddi3(0x8000000000000000, 2, 0x0); + test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); +} + +fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { + const r = __umoddi3(a, b); + testing.expect(r == expected_r); +} + +pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + + const d = __divsi3(a, b); + rem.* = a -% (d * b); + return d; +} + +test "test_divmodsi4" { + const cases = [_][4]i32{ + [_]i32{ 0, 1, 0, 0 }, + [_]i32{ 0, -1, 0, 0 }, + [_]i32{ 2, 1, 2, 0 }, + [_]i32{ 2, -1, -2, 0 }, + [_]i32{ -2, 1, -2, 0 }, + [_]i32{ -2, -1, 2, 0 }, + [_]i32{ 7, 5, 1, 2 }, + [_]i32{ -7, 5, -1, -2 }, + [_]i32{ 19, 5, 3, 4 }, + [_]i32{ 19, -5, -3, 4 }, + + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 8, @bitCast(i32, @as(u32, 0xf0000000)), 0 }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000007)), 8, @bitCast(i32, @as(u32, 0xf0000001)), -1 }, + }; + + for (cases) |case| { + test_one_divmodsi4(case[0], case[1], case[2], case[3]); + } +} + +fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void { + var r: i32 = undefined; + const q: i32 = __divmodsi4(a, b, &r); + testing.expect(q == expected_q and r == expected_r); +} + +pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 { + @setRuntimeSafety(builtin.is_test); + + const d = __udivsi3(a, b); + rem.* = @bitCast(u32, @bitCast(i32, a) -% (@bitCast(i32, d) * @bitCast(i32, b))); + return d; +} + +pub fn __divsi3(n: i32, d: i32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + + // Set aside the sign of the quotient. + const sign = @bitCast(u32, (n ^ d) >> 31); + // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). + const abs_n = (n ^ (n >> 31)) -% (n >> 31); + const abs_d = (d ^ (d >> 31)) -% (d >> 31); + // abs(a) / abs(b) + const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d); + // Apply sign of quotient to result and return. + return @bitCast(i32, (res ^ sign) -% sign); +} + +test "test_divsi3" { + const cases = [_][3]i32{ + [_]i32{ 0, 1, 0 }, + [_]i32{ 0, -1, 0 }, + [_]i32{ 2, 1, 2 }, + [_]i32{ 2, -1, -2 }, + [_]i32{ -2, 1, -2 }, + [_]i32{ -2, -1, 2 }, + + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 1, @bitCast(i32, @as(u32, 0x80000000)) }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -1, @bitCast(i32, @as(u32, 0x80000000)) }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -2, 0x40000000 }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 2, @bitCast(i32, @as(u32, 0xC0000000)) }, + }; + + for (cases) |case| { + test_one_divsi3(case[0], case[1], case[2]); + } +} + +fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void { + const q: i32 = __divsi3(a, b); + testing.expect(q == expected_q); +} + +pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 { + @setRuntimeSafety(builtin.is_test); + + const n_uword_bits: c_uint = u32.bit_count; + // special cases + if (d == 0) return 0; // ?! + if (n == 0) return 0; + var sr = @bitCast(c_uint, @as(c_int, @clz(u32, d)) - @as(c_int, @clz(u32, n))); + // 0 <= sr <= n_uword_bits - 1 or sr large + if (sr > n_uword_bits - 1) { + // d > r + return 0; + } + if (sr == n_uword_bits - 1) { + // d == 1 + return n; + } + sr += 1; + // 1 <= sr <= n_uword_bits - 1 + // Not a special case + var q: u32 = n << @intCast(u5, n_uword_bits - sr); + var r: u32 = n >> @intCast(u5, sr); + var carry: u32 = 0; + while (sr > 0) : (sr -= 1) { + // r:q = ((r:q) << 1) | carry + r = (r << 1) | (q >> @intCast(u5, n_uword_bits - 1)); + q = (q << 1) | carry; + // carry = 0; + // if (r.all >= d.all) + // { + // r.all -= d.all; + // carry = 1; + // } + const s = @intCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1); + carry = @intCast(u32, s & 1); + r -= d & @bitCast(u32, s); + } + q = (q << 1) | carry; + return q; +} + +test "test_udivsi3" { + const cases = [_][3]u32{ + [_]u32{ 0x00000000, 0x00000001, 0x00000000 }, + [_]u32{ 0x00000000, 0x00000002, 0x00000000 }, + [_]u32{ 0x00000000, 0x00000003, 0x00000000 }, + [_]u32{ 0x00000000, 0x00000010, 0x00000000 }, + [_]u32{ 0x00000000, 0x078644FA, 0x00000000 }, + [_]u32{ 0x00000000, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x00000000, 0x80000000, 0x00000000 }, + [_]u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x00000001, 0x00000001, 0x00000001 }, + [_]u32{ 0x00000001, 0x00000002, 0x00000000 }, + [_]u32{ 0x00000001, 0x00000003, 0x00000000 }, + [_]u32{ 0x00000001, 0x00000010, 0x00000000 }, + [_]u32{ 0x00000001, 0x078644FA, 0x00000000 }, + [_]u32{ 0x00000001, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x00000001, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x00000001, 0x80000000, 0x00000000 }, + [_]u32{ 0x00000001, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x00000001, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x00000001, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x00000002, 0x00000001, 0x00000002 }, + [_]u32{ 0x00000002, 0x00000002, 0x00000001 }, + [_]u32{ 0x00000002, 0x00000003, 0x00000000 }, + [_]u32{ 0x00000002, 0x00000010, 0x00000000 }, + [_]u32{ 0x00000002, 0x078644FA, 0x00000000 }, + [_]u32{ 0x00000002, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x00000002, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x00000002, 0x80000000, 0x00000000 }, + [_]u32{ 0x00000002, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x00000002, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x00000002, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x00000003, 0x00000001, 0x00000003 }, + [_]u32{ 0x00000003, 0x00000002, 0x00000001 }, + [_]u32{ 0x00000003, 0x00000003, 0x00000001 }, + [_]u32{ 0x00000003, 0x00000010, 0x00000000 }, + [_]u32{ 0x00000003, 0x078644FA, 0x00000000 }, + [_]u32{ 0x00000003, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x00000003, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x00000003, 0x80000000, 0x00000000 }, + [_]u32{ 0x00000003, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x00000003, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x00000003, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x00000010, 0x00000001, 0x00000010 }, + [_]u32{ 0x00000010, 0x00000002, 0x00000008 }, + [_]u32{ 0x00000010, 0x00000003, 0x00000005 }, + [_]u32{ 0x00000010, 0x00000010, 0x00000001 }, + [_]u32{ 0x00000010, 0x078644FA, 0x00000000 }, + [_]u32{ 0x00000010, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x00000010, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x00000010, 0x80000000, 0x00000000 }, + [_]u32{ 0x00000010, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x00000010, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x00000010, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x078644FA, 0x00000001, 0x078644FA }, + [_]u32{ 0x078644FA, 0x00000002, 0x03C3227D }, + [_]u32{ 0x078644FA, 0x00000003, 0x028216FE }, + [_]u32{ 0x078644FA, 0x00000010, 0x0078644F }, + [_]u32{ 0x078644FA, 0x078644FA, 0x00000001 }, + [_]u32{ 0x078644FA, 0x0747AE14, 0x00000001 }, + [_]u32{ 0x078644FA, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x078644FA, 0x80000000, 0x00000000 }, + [_]u32{ 0x078644FA, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x078644FA, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x078644FA, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x0747AE14, 0x00000001, 0x0747AE14 }, + [_]u32{ 0x0747AE14, 0x00000002, 0x03A3D70A }, + [_]u32{ 0x0747AE14, 0x00000003, 0x026D3A06 }, + [_]u32{ 0x0747AE14, 0x00000010, 0x00747AE1 }, + [_]u32{ 0x0747AE14, 0x078644FA, 0x00000000 }, + [_]u32{ 0x0747AE14, 0x0747AE14, 0x00000001 }, + [_]u32{ 0x0747AE14, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x0747AE14, 0x80000000, 0x00000000 }, + [_]u32{ 0x0747AE14, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x0747AE14, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x0747AE14, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x7FFFFFFF, 0x00000001, 0x7FFFFFFF }, + [_]u32{ 0x7FFFFFFF, 0x00000002, 0x3FFFFFFF }, + [_]u32{ 0x7FFFFFFF, 0x00000003, 0x2AAAAAAA }, + [_]u32{ 0x7FFFFFFF, 0x00000010, 0x07FFFFFF }, + [_]u32{ 0x7FFFFFFF, 0x078644FA, 0x00000011 }, + [_]u32{ 0x7FFFFFFF, 0x0747AE14, 0x00000011 }, + [_]u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000001 }, + [_]u32{ 0x7FFFFFFF, 0x80000000, 0x00000000 }, + [_]u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x80000000, 0x00000001, 0x80000000 }, + [_]u32{ 0x80000000, 0x00000002, 0x40000000 }, + [_]u32{ 0x80000000, 0x00000003, 0x2AAAAAAA }, + [_]u32{ 0x80000000, 0x00000010, 0x08000000 }, + [_]u32{ 0x80000000, 0x078644FA, 0x00000011 }, + [_]u32{ 0x80000000, 0x0747AE14, 0x00000011 }, + [_]u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 }, + [_]u32{ 0x80000000, 0x80000000, 0x00000001 }, + [_]u32{ 0x80000000, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x80000000, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x80000000, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0xFFFFFFFD, 0x00000001, 0xFFFFFFFD }, + [_]u32{ 0xFFFFFFFD, 0x00000002, 0x7FFFFFFE }, + [_]u32{ 0xFFFFFFFD, 0x00000003, 0x55555554 }, + [_]u32{ 0xFFFFFFFD, 0x00000010, 0x0FFFFFFF }, + [_]u32{ 0xFFFFFFFD, 0x078644FA, 0x00000022 }, + [_]u32{ 0xFFFFFFFD, 0x0747AE14, 0x00000023 }, + [_]u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x00000001 }, + [_]u32{ 0xFFFFFFFD, 0x80000000, 0x00000001 }, + [_]u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000001 }, + [_]u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE }, + [_]u32{ 0xFFFFFFFE, 0x00000002, 0x7FFFFFFF }, + [_]u32{ 0xFFFFFFFE, 0x00000003, 0x55555554 }, + [_]u32{ 0xFFFFFFFE, 0x00000010, 0x0FFFFFFF }, + [_]u32{ 0xFFFFFFFE, 0x078644FA, 0x00000022 }, + [_]u32{ 0xFFFFFFFE, 0x0747AE14, 0x00000023 }, + [_]u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000002 }, + [_]u32{ 0xFFFFFFFE, 0x80000000, 0x00000001 }, + [_]u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 }, + [_]u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000001 }, + [_]u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF }, + [_]u32{ 0xFFFFFFFF, 0x00000002, 0x7FFFFFFF }, + [_]u32{ 0xFFFFFFFF, 0x00000003, 0x55555555 }, + [_]u32{ 0xFFFFFFFF, 0x00000010, 0x0FFFFFFF }, + [_]u32{ 0xFFFFFFFF, 0x078644FA, 0x00000022 }, + [_]u32{ 0xFFFFFFFF, 0x0747AE14, 0x00000023 }, + [_]u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000002 }, + [_]u32{ 0xFFFFFFFF, 0x80000000, 0x00000001 }, + [_]u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000001 }, + [_]u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 }, + [_]u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 }, + }; + + for (cases) |case| { + test_one_udivsi3(case[0], case[1], case[2]); + } +} + +fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { + const q: u32 = __udivsi3(a, b); + testing.expect(q == expected_q); +} + +pub fn __modsi3(n: i32, d: i32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + + return n -% __divsi3(n, d) *% d; +} + +test "test_modsi3" { + const cases = [_][3]i32{ + [_]i32{ 0, 1, 0 }, + [_]i32{ 0, -1, 0 }, + [_]i32{ 5, 3, 2 }, + [_]i32{ 5, -3, 2 }, + [_]i32{ -5, 3, -2 }, + [_]i32{ -5, -3, -2 }, + [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 1, 0x0 }, + [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 2, 0x0 }, + [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -2, 0x0 }, + [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), 3, -2 }, + [_]i32{ @bitCast(i32, @intCast(u32, 0x80000000)), -3, -2 }, + }; + + for (cases) |case| { + test_one_modsi3(case[0], case[1], case[2]); + } +} + +fn test_one_modsi3(a: i32, b: i32, expected_r: i32) void { + const r: i32 = __modsi3(a, b); + testing.expect(r == expected_r); +} + +pub fn __umodsi3(n: u32, d: u32) callconv(.C) u32 { + @setRuntimeSafety(builtin.is_test); + + return n -% __udivsi3(n, d) *% d; +} + +test "test_umodsi3" { + const cases = [_][3]u32{ + [_]u32{ 0x00000000, 0x00000001, 0x00000000 }, + [_]u32{ 0x00000000, 0x00000002, 0x00000000 }, + [_]u32{ 0x00000000, 0x00000003, 0x00000000 }, + [_]u32{ 0x00000000, 0x00000010, 0x00000000 }, + [_]u32{ 0x00000000, 0x078644FA, 0x00000000 }, + [_]u32{ 0x00000000, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x00000000, 0x80000000, 0x00000000 }, + [_]u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 }, + [_]u32{ 0x00000001, 0x00000001, 0x00000000 }, + [_]u32{ 0x00000001, 0x00000002, 0x00000001 }, + [_]u32{ 0x00000001, 0x00000003, 0x00000001 }, + [_]u32{ 0x00000001, 0x00000010, 0x00000001 }, + [_]u32{ 0x00000001, 0x078644FA, 0x00000001 }, + [_]u32{ 0x00000001, 0x0747AE14, 0x00000001 }, + [_]u32{ 0x00000001, 0x7FFFFFFF, 0x00000001 }, + [_]u32{ 0x00000001, 0x80000000, 0x00000001 }, + [_]u32{ 0x00000001, 0xFFFFFFFD, 0x00000001 }, + [_]u32{ 0x00000001, 0xFFFFFFFE, 0x00000001 }, + [_]u32{ 0x00000001, 0xFFFFFFFF, 0x00000001 }, + [_]u32{ 0x00000002, 0x00000001, 0x00000000 }, + [_]u32{ 0x00000002, 0x00000002, 0x00000000 }, + [_]u32{ 0x00000002, 0x00000003, 0x00000002 }, + [_]u32{ 0x00000002, 0x00000010, 0x00000002 }, + [_]u32{ 0x00000002, 0x078644FA, 0x00000002 }, + [_]u32{ 0x00000002, 0x0747AE14, 0x00000002 }, + [_]u32{ 0x00000002, 0x7FFFFFFF, 0x00000002 }, + [_]u32{ 0x00000002, 0x80000000, 0x00000002 }, + [_]u32{ 0x00000002, 0xFFFFFFFD, 0x00000002 }, + [_]u32{ 0x00000002, 0xFFFFFFFE, 0x00000002 }, + [_]u32{ 0x00000002, 0xFFFFFFFF, 0x00000002 }, + [_]u32{ 0x00000003, 0x00000001, 0x00000000 }, + [_]u32{ 0x00000003, 0x00000002, 0x00000001 }, + [_]u32{ 0x00000003, 0x00000003, 0x00000000 }, + [_]u32{ 0x00000003, 0x00000010, 0x00000003 }, + [_]u32{ 0x00000003, 0x078644FA, 0x00000003 }, + [_]u32{ 0x00000003, 0x0747AE14, 0x00000003 }, + [_]u32{ 0x00000003, 0x7FFFFFFF, 0x00000003 }, + [_]u32{ 0x00000003, 0x80000000, 0x00000003 }, + [_]u32{ 0x00000003, 0xFFFFFFFD, 0x00000003 }, + [_]u32{ 0x00000003, 0xFFFFFFFE, 0x00000003 }, + [_]u32{ 0x00000003, 0xFFFFFFFF, 0x00000003 }, + [_]u32{ 0x00000010, 0x00000001, 0x00000000 }, + [_]u32{ 0x00000010, 0x00000002, 0x00000000 }, + [_]u32{ 0x00000010, 0x00000003, 0x00000001 }, + [_]u32{ 0x00000010, 0x00000010, 0x00000000 }, + [_]u32{ 0x00000010, 0x078644FA, 0x00000010 }, + [_]u32{ 0x00000010, 0x0747AE14, 0x00000010 }, + [_]u32{ 0x00000010, 0x7FFFFFFF, 0x00000010 }, + [_]u32{ 0x00000010, 0x80000000, 0x00000010 }, + [_]u32{ 0x00000010, 0xFFFFFFFD, 0x00000010 }, + [_]u32{ 0x00000010, 0xFFFFFFFE, 0x00000010 }, + [_]u32{ 0x00000010, 0xFFFFFFFF, 0x00000010 }, + [_]u32{ 0x078644FA, 0x00000001, 0x00000000 }, + [_]u32{ 0x078644FA, 0x00000002, 0x00000000 }, + [_]u32{ 0x078644FA, 0x00000003, 0x00000000 }, + [_]u32{ 0x078644FA, 0x00000010, 0x0000000A }, + [_]u32{ 0x078644FA, 0x078644FA, 0x00000000 }, + [_]u32{ 0x078644FA, 0x0747AE14, 0x003E96E6 }, + [_]u32{ 0x078644FA, 0x7FFFFFFF, 0x078644FA }, + [_]u32{ 0x078644FA, 0x80000000, 0x078644FA }, + [_]u32{ 0x078644FA, 0xFFFFFFFD, 0x078644FA }, + [_]u32{ 0x078644FA, 0xFFFFFFFE, 0x078644FA }, + [_]u32{ 0x078644FA, 0xFFFFFFFF, 0x078644FA }, + [_]u32{ 0x0747AE14, 0x00000001, 0x00000000 }, + [_]u32{ 0x0747AE14, 0x00000002, 0x00000000 }, + [_]u32{ 0x0747AE14, 0x00000003, 0x00000002 }, + [_]u32{ 0x0747AE14, 0x00000010, 0x00000004 }, + [_]u32{ 0x0747AE14, 0x078644FA, 0x0747AE14 }, + [_]u32{ 0x0747AE14, 0x0747AE14, 0x00000000 }, + [_]u32{ 0x0747AE14, 0x7FFFFFFF, 0x0747AE14 }, + [_]u32{ 0x0747AE14, 0x80000000, 0x0747AE14 }, + [_]u32{ 0x0747AE14, 0xFFFFFFFD, 0x0747AE14 }, + [_]u32{ 0x0747AE14, 0xFFFFFFFE, 0x0747AE14 }, + [_]u32{ 0x0747AE14, 0xFFFFFFFF, 0x0747AE14 }, + [_]u32{ 0x7FFFFFFF, 0x00000001, 0x00000000 }, + [_]u32{ 0x7FFFFFFF, 0x00000002, 0x00000001 }, + [_]u32{ 0x7FFFFFFF, 0x00000003, 0x00000001 }, + [_]u32{ 0x7FFFFFFF, 0x00000010, 0x0000000F }, + [_]u32{ 0x7FFFFFFF, 0x078644FA, 0x00156B65 }, + [_]u32{ 0x7FFFFFFF, 0x0747AE14, 0x043D70AB }, + [_]u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF }, + [_]u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x7FFFFFFF }, + [_]u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x7FFFFFFF }, + [_]u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF }, + [_]u32{ 0x80000000, 0x00000001, 0x00000000 }, + [_]u32{ 0x80000000, 0x00000002, 0x00000000 }, + [_]u32{ 0x80000000, 0x00000003, 0x00000002 }, + [_]u32{ 0x80000000, 0x00000010, 0x00000000 }, + [_]u32{ 0x80000000, 0x078644FA, 0x00156B66 }, + [_]u32{ 0x80000000, 0x0747AE14, 0x043D70AC }, + [_]u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 }, + [_]u32{ 0x80000000, 0x80000000, 0x00000000 }, + [_]u32{ 0x80000000, 0xFFFFFFFD, 0x80000000 }, + [_]u32{ 0x80000000, 0xFFFFFFFE, 0x80000000 }, + [_]u32{ 0x80000000, 0xFFFFFFFF, 0x80000000 }, + [_]u32{ 0xFFFFFFFD, 0x00000001, 0x00000000 }, + [_]u32{ 0xFFFFFFFD, 0x00000002, 0x00000001 }, + [_]u32{ 0xFFFFFFFD, 0x00000003, 0x00000001 }, + [_]u32{ 0xFFFFFFFD, 0x00000010, 0x0000000D }, + [_]u32{ 0xFFFFFFFD, 0x078644FA, 0x002AD6C9 }, + [_]u32{ 0xFFFFFFFD, 0x0747AE14, 0x01333341 }, + [_]u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x7FFFFFFE }, + [_]u32{ 0xFFFFFFFD, 0x80000000, 0x7FFFFFFD }, + [_]u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000000 }, + [_]u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFD }, + [_]u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFD }, + [_]u32{ 0xFFFFFFFE, 0x00000001, 0x00000000 }, + [_]u32{ 0xFFFFFFFE, 0x00000002, 0x00000000 }, + [_]u32{ 0xFFFFFFFE, 0x00000003, 0x00000002 }, + [_]u32{ 0xFFFFFFFE, 0x00000010, 0x0000000E }, + [_]u32{ 0xFFFFFFFE, 0x078644FA, 0x002AD6CA }, + [_]u32{ 0xFFFFFFFE, 0x0747AE14, 0x01333342 }, + [_]u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000000 }, + [_]u32{ 0xFFFFFFFE, 0x80000000, 0x7FFFFFFE }, + [_]u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 }, + [_]u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000000 }, + [_]u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE }, + [_]u32{ 0xFFFFFFFF, 0x00000001, 0x00000000 }, + [_]u32{ 0xFFFFFFFF, 0x00000002, 0x00000001 }, + [_]u32{ 0xFFFFFFFF, 0x00000003, 0x00000000 }, + [_]u32{ 0xFFFFFFFF, 0x00000010, 0x0000000F }, + [_]u32{ 0xFFFFFFFF, 0x078644FA, 0x002AD6CB }, + [_]u32{ 0xFFFFFFFF, 0x0747AE14, 0x01333343 }, + [_]u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001 }, + [_]u32{ 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF }, + [_]u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000002 }, + [_]u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 }, + [_]u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, + }; + + for (cases) |case| { + test_one_umodsi3(case[0], case[1], case[2]); + } +} + +fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void { + const r: u32 = __umodsi3(a, b); + testing.expect(r == expected_r); +} diff --git a/lib/std/special/compiler_rt/udivmoddi4.zig b/lib/std/special/compiler_rt/udivmoddi4.zig deleted file mode 100644 index 79f0f39986..0000000000 --- a/lib/std/special/compiler_rt/udivmoddi4.zig +++ /dev/null @@ -1,11 +0,0 @@ -const udivmod = @import("udivmod.zig").udivmod; -const builtin = @import("builtin"); - -pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 { - @setRuntimeSafety(builtin.is_test); - return udivmod(u64, a, b, maybe_rem); -} - -test "import udivmoddi4" { - _ = @import("udivmoddi4_test.zig"); -} diff --git a/lib/std/special/compiler_rt/udivmoddi4_test.zig b/lib/std/special/compiler_rt/udivmoddi4_test.zig index 17581fc569..48a38faa04 100644 --- a/lib/std/special/compiler_rt/udivmoddi4_test.zig +++ b/lib/std/special/compiler_rt/udivmoddi4_test.zig @@ -1,6 +1,6 @@ // Disable formatting to avoid unnecessary source repository bloat. // zig fmt: off -const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; +const __udivmoddi4 = @import("int.zig").__udivmoddi4; const testing = @import("std").testing; fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void { |
