zig

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

int.zig (27737B) - Raw


      1 //! Builtin functions that operate on integer types
      2 
      3 const builtin = @import("builtin");
      4 const std = @import("std");
      5 const testing = std.testing;
      6 const maxInt = std.math.maxInt;
      7 const minInt = std.math.minInt;
      8 const arch = builtin.cpu.arch;
      9 const common = @import("common.zig");
     10 const udivmod = @import("udivmod.zig").udivmod;
     11 const __divti3 = @import("divti3.zig").__divti3;
     12 
     13 pub const panic = common.panic;
     14 
     15 comptime {
     16     @export(&__divmodti4, .{ .name = "__divmodti4", .linkage = common.linkage, .visibility = common.visibility });
     17     @export(&__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage, .visibility = common.visibility });
     18     @export(&__divmoddi4, .{ .name = "__divmoddi4", .linkage = common.linkage, .visibility = common.visibility });
     19     if (common.want_aeabi) {
     20         @export(&__aeabi_idiv, .{ .name = "__aeabi_idiv", .linkage = common.linkage, .visibility = common.visibility });
     21         @export(&__aeabi_uidiv, .{ .name = "__aeabi_uidiv", .linkage = common.linkage, .visibility = common.visibility });
     22     } else {
     23         @export(&__divsi3, .{ .name = "__divsi3", .linkage = common.linkage, .visibility = common.visibility });
     24         @export(&__udivsi3, .{ .name = "__udivsi3", .linkage = common.linkage, .visibility = common.visibility });
     25     }
     26     @export(&__divdi3, .{ .name = "__divdi3", .linkage = common.linkage, .visibility = common.visibility });
     27     @export(&__udivdi3, .{ .name = "__udivdi3", .linkage = common.linkage, .visibility = common.visibility });
     28     @export(&__modsi3, .{ .name = "__modsi3", .linkage = common.linkage, .visibility = common.visibility });
     29     @export(&__moddi3, .{ .name = "__moddi3", .linkage = common.linkage, .visibility = common.visibility });
     30     @export(&__umodsi3, .{ .name = "__umodsi3", .linkage = common.linkage, .visibility = common.visibility });
     31     @export(&__umoddi3, .{ .name = "__umoddi3", .linkage = common.linkage, .visibility = common.visibility });
     32     @export(&__divmodsi4, .{ .name = "__divmodsi4", .linkage = common.linkage, .visibility = common.visibility });
     33     @export(&__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = common.linkage, .visibility = common.visibility });
     34 }
     35 
     36 pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 {
     37     const d = __divti3(a, b);
     38     rem.* = a -% (d * b);
     39     return d;
     40 }
     41 
     42 test "test_divmodti4" {
     43     const cases = [_][4]i128{
     44         [_]i128{ 0, 1, 0, 0 },
     45         [_]i128{ 0, -1, 0, 0 },
     46         [_]i128{ 2, 1, 2, 0 },
     47         [_]i128{ 2, -1, -2, 0 },
     48         [_]i128{ -2, 1, -2, 0 },
     49         [_]i128{ -2, -1, 2, 0 },
     50         [_]i128{ 7, 5, 1, 2 },
     51         [_]i128{ -7, 5, -1, -2 },
     52         [_]i128{ 19, 5, 3, 4 },
     53         [_]i128{ 19, -5, -3, 4 },
     54         [_]i128{ @bitCast(@as(u128, 0x80000000000000000000000000000000)), 8, @bitCast(@as(u128, 0xf0000000000000000000000000000000)), 0 },
     55         [_]i128{ @bitCast(@as(u128, 0x80000000000000000000000000000007)), 8, @bitCast(@as(u128, 0xf0000000000000000000000000000001)), -1 },
     56     };
     57 
     58     for (cases) |case| {
     59         try test_one_divmodti4(case[0], case[1], case[2], case[3]);
     60     }
     61 }
     62 
     63 fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !void {
     64     var r: i128 = undefined;
     65     const q: i128 = __divmodti4(a, b, &r);
     66     try testing.expect(q == expected_q and r == expected_r);
     67 }
     68 
     69 pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 {
     70     const d = __divdi3(a, b);
     71     rem.* = a -% (d * b);
     72     return d;
     73 }
     74 
     75 fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
     76     var r: i64 = undefined;
     77     const q: i64 = __divmoddi4(a, b, &r);
     78     try testing.expect(q == expected_q and r == expected_r);
     79 }
     80 
     81 const cases__divmoddi4 =
     82     [_][4]i64{
     83         [_]i64{ 0, 1, 0, 0 },
     84         [_]i64{ 0, -1, 0, 0 },
     85         [_]i64{ 2, 1, 2, 0 },
     86         [_]i64{ 2, -1, -2, 0 },
     87         [_]i64{ -2, 1, -2, 0 },
     88         [_]i64{ -2, -1, 2, 0 },
     89         [_]i64{ 7, 5, 1, 2 },
     90         [_]i64{ -7, 5, -1, -2 },
     91         [_]i64{ 19, 5, 3, 4 },
     92         [_]i64{ 19, -5, -3, 4 },
     93         [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 },
     94         [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 },
     95     };
     96 
     97 test "test_divmoddi4" {
     98     for (cases__divmoddi4) |case| {
     99         try test_one_divmoddi4(case[0], case[1], case[2], case[3]);
    100     }
    101 }
    102 
    103 pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 {
    104     return udivmod(u64, a, b, maybe_rem);
    105 }
    106 
    107 test "test_udivmoddi4" {
    108     _ = @import("udivmoddi4_test.zig");
    109 }
    110 
    111 pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 {
    112     // Set aside the sign of the quotient.
    113     const sign: u64 = @bitCast((a ^ b) >> 63);
    114     // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
    115     const abs_a = (a ^ (a >> 63)) -% (a >> 63);
    116     const abs_b = (b ^ (b >> 63)) -% (b >> 63);
    117     // Unsigned division
    118     const res = __udivmoddi4(@bitCast(abs_a), @bitCast(abs_b), null);
    119     // Apply sign of quotient to result and return.
    120     return @bitCast((res ^ sign) -% sign);
    121 }
    122 
    123 test "test_divdi3" {
    124     const cases = [_][3]i64{
    125         [_]i64{ 0, 1, 0 },
    126         [_]i64{ 0, -1, 0 },
    127         [_]i64{ 2, 1, 2 },
    128         [_]i64{ 2, -1, -2 },
    129         [_]i64{ -2, 1, -2 },
    130         [_]i64{ -2, -1, 2 },
    131 
    132         [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))) },
    133         [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -1, @as(i64, @bitCast(@as(u64, 0x8000000000000000))) },
    134         [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), -2, 0x4000000000000000 },
    135         [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 2, @as(i64, @bitCast(@as(u64, 0xC000000000000000))) },
    136     };
    137 
    138     for (cases) |case| {
    139         try test_one_divdi3(case[0], case[1], case[2]);
    140     }
    141 }
    142 
    143 fn test_one_divdi3(a: i64, b: i64, expected_q: i64) !void {
    144     const q: i64 = __divdi3(a, b);
    145     try testing.expect(q == expected_q);
    146 }
    147 
    148 pub fn __moddi3(a: i64, b: i64) callconv(.c) i64 {
    149     // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
    150     const abs_a = (a ^ (a >> 63)) -% (a >> 63);
    151     const abs_b = (b ^ (b >> 63)) -% (b >> 63);
    152     // Unsigned division
    153     var r: u64 = undefined;
    154     _ = __udivmoddi4(@bitCast(abs_a), @bitCast(abs_b), &r);
    155     // Apply the sign of the dividend and return.
    156     return (@as(i64, @bitCast(r)) ^ (a >> 63)) -% (a >> 63);
    157 }
    158 
    159 test "test_moddi3" {
    160     const cases = [_][3]i64{
    161         [_]i64{ 0, 1, 0 },
    162         [_]i64{ 0, -1, 0 },
    163         [_]i64{ 5, 3, 2 },
    164         [_]i64{ 5, -3, 2 },
    165         [_]i64{ -5, 3, -2 },
    166         [_]i64{ -5, -3, -2 },
    167 
    168         [_]i64{ @bitCast(@as(u64, 0x8000000000000000)), 1, 0 },
    169         [_]i64{ @bitCast(@as(u64, 0x8000000000000000)), -1, 0 },
    170         [_]i64{ @bitCast(@as(u64, 0x8000000000000000)), 2, 0 },
    171         [_]i64{ @bitCast(@as(u64, 0x8000000000000000)), -2, 0 },
    172         [_]i64{ @bitCast(@as(u64, 0x8000000000000000)), 3, -2 },
    173         [_]i64{ @bitCast(@as(u64, 0x8000000000000000)), -3, -2 },
    174     };
    175 
    176     for (cases) |case| {
    177         try test_one_moddi3(case[0], case[1], case[2]);
    178     }
    179 }
    180 
    181 fn test_one_moddi3(a: i64, b: i64, expected_r: i64) !void {
    182     const r: i64 = __moddi3(a, b);
    183     try testing.expect(r == expected_r);
    184 }
    185 
    186 pub fn __udivdi3(a: u64, b: u64) callconv(.c) u64 {
    187     return __udivmoddi4(a, b, null);
    188 }
    189 
    190 pub fn __umoddi3(a: u64, b: u64) callconv(.c) u64 {
    191     var r: u64 = undefined;
    192     _ = __udivmoddi4(a, b, &r);
    193     return r;
    194 }
    195 
    196 test "test_umoddi3" {
    197     try test_one_umoddi3(0, 1, 0);
    198     try test_one_umoddi3(2, 1, 0);
    199     try test_one_umoddi3(0x8000000000000000, 1, 0x0);
    200     try test_one_umoddi3(0x8000000000000000, 2, 0x0);
    201     try test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1);
    202 }
    203 
    204 fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void {
    205     const r = __umoddi3(a, b);
    206     try testing.expect(r == expected_r);
    207 }
    208 
    209 pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 {
    210     const d = __divsi3(a, b);
    211     rem.* = a -% (d * b);
    212     return d;
    213 }
    214 
    215 const cases__divmodsi4 =
    216     [_][4]i32{
    217         [_]i32{ 0, 1, 0, 0 },
    218         [_]i32{ 0, -1, 0, 0 },
    219         [_]i32{ 2, 1, 2, 0 },
    220         [_]i32{ 2, -1, -2, 0 },
    221         [_]i32{ -2, 1, -2, 0 },
    222         [_]i32{ -2, -1, 2, 0 },
    223         [_]i32{ 7, 5, 1, 2 },
    224         [_]i32{ -7, 5, -1, -2 },
    225         [_]i32{ 19, 5, 3, 4 },
    226         [_]i32{ 19, -5, -3, 4 },
    227         [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 },
    228         [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 },
    229     };
    230 
    231 fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
    232     var r: i32 = undefined;
    233     const q: i32 = __divmodsi4(a, b, &r);
    234     try testing.expect(q == expected_q and r == expected_r);
    235 }
    236 
    237 test "test_divmodsi4" {
    238     for (cases__divmodsi4) |case| {
    239         try test_one_divmodsi4(case[0], case[1], case[2], case[3]);
    240     }
    241 }
    242 
    243 pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 {
    244     const d = __udivsi3(a, b);
    245     rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b))));
    246     return d;
    247 }
    248 
    249 pub fn __divsi3(n: i32, d: i32) callconv(.c) i32 {
    250     return div_i32(n, d);
    251 }
    252 
    253 fn __aeabi_idiv(n: i32, d: i32) callconv(.{ .arm_aapcs = .{} }) i32 {
    254     return div_i32(n, d);
    255 }
    256 
    257 inline fn div_i32(n: i32, d: i32) i32 {
    258     // Set aside the sign of the quotient.
    259     const sign: u32 = @bitCast((n ^ d) >> 31);
    260     // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
    261     const abs_n = (n ^ (n >> 31)) -% (n >> 31);
    262     const abs_d = (d ^ (d >> 31)) -% (d >> 31);
    263     // abs(a) / abs(b)
    264     const res = @as(u32, @bitCast(abs_n)) / @as(u32, @bitCast(abs_d));
    265     // Apply sign of quotient to result and return.
    266     return @bitCast((res ^ sign) -% sign);
    267 }
    268 
    269 test "test_divsi3" {
    270     const cases = [_][3]i32{
    271         [_]i32{ 0, 1, 0 },
    272         [_]i32{ 0, -1, 0 },
    273         [_]i32{ 2, 1, 2 },
    274         [_]i32{ 2, -1, -2 },
    275         [_]i32{ -2, 1, -2 },
    276         [_]i32{ -2, -1, 2 },
    277 
    278         [_]i32{ @bitCast(@as(u32, 0x80000000)), 1, @bitCast(@as(u32, 0x80000000)) },
    279         [_]i32{ @bitCast(@as(u32, 0x80000000)), -1, @bitCast(@as(u32, 0x80000000)) },
    280         [_]i32{ @bitCast(@as(u32, 0x80000000)), -2, 0x40000000 },
    281         [_]i32{ @bitCast(@as(u32, 0x80000000)), 2, @bitCast(@as(u32, 0xC0000000)) },
    282     };
    283 
    284     for (cases) |case| {
    285         try test_one_divsi3(case[0], case[1], case[2]);
    286     }
    287 }
    288 
    289 fn test_one_divsi3(a: i32, b: i32, expected_q: i32) !void {
    290     const q: i32 = __divsi3(a, b);
    291     try testing.expect(q == expected_q);
    292 }
    293 
    294 pub fn __udivsi3(n: u32, d: u32) callconv(.c) u32 {
    295     return div_u32(n, d);
    296 }
    297 
    298 fn __aeabi_uidiv(n: u32, d: u32) callconv(.{ .arm_aapcs = .{} }) u32 {
    299     return div_u32(n, d);
    300 }
    301 
    302 inline fn div_u32(n: u32, d: u32) u32 {
    303     const n_uword_bits: c_uint = 32;
    304     // special cases
    305     if (d == 0) return 0; // ?!
    306     if (n == 0) return 0;
    307     var sr = @as(c_uint, @bitCast(@as(c_int, @clz(d)) - @as(c_int, @clz(n))));
    308     // 0 <= sr <= n_uword_bits - 1 or sr large
    309     if (sr > n_uword_bits - 1) {
    310         // d > r
    311         return 0;
    312     }
    313     if (sr == n_uword_bits - 1) {
    314         // d == 1
    315         return n;
    316     }
    317     sr += 1;
    318     // 1 <= sr <= n_uword_bits - 1
    319     // Not a special case
    320     var q: u32 = n << @intCast(n_uword_bits - sr);
    321     var r: u32 = n >> @intCast(sr);
    322     var carry: u32 = 0;
    323     while (sr > 0) : (sr -= 1) {
    324         // r:q = ((r:q)  << 1) | carry
    325         r = (r << 1) | (q >> @intCast(n_uword_bits - 1));
    326         q = (q << 1) | carry;
    327         // carry = 0;
    328         // if (r.all >= d.all)
    329         // {
    330         //      r.all -= d.all;
    331         //      carry = 1;
    332         // }
    333         const s = @as(i32, @bitCast(d -% r -% 1)) >> @intCast(n_uword_bits - 1);
    334         carry = @intCast(s & 1);
    335         r -= d & @as(u32, @bitCast(s));
    336     }
    337     q = (q << 1) | carry;
    338     return q;
    339 }
    340 
    341 test "test_udivsi3" {
    342     const cases = [_][3]u32{
    343         [_]u32{ 0x00000000, 0x00000001, 0x00000000 },
    344         [_]u32{ 0x00000000, 0x00000002, 0x00000000 },
    345         [_]u32{ 0x00000000, 0x00000003, 0x00000000 },
    346         [_]u32{ 0x00000000, 0x00000010, 0x00000000 },
    347         [_]u32{ 0x00000000, 0x078644FA, 0x00000000 },
    348         [_]u32{ 0x00000000, 0x0747AE14, 0x00000000 },
    349         [_]u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 },
    350         [_]u32{ 0x00000000, 0x80000000, 0x00000000 },
    351         [_]u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 },
    352         [_]u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 },
    353         [_]u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 },
    354         [_]u32{ 0x00000001, 0x00000001, 0x00000001 },
    355         [_]u32{ 0x00000001, 0x00000002, 0x00000000 },
    356         [_]u32{ 0x00000001, 0x00000003, 0x00000000 },
    357         [_]u32{ 0x00000001, 0x00000010, 0x00000000 },
    358         [_]u32{ 0x00000001, 0x078644FA, 0x00000000 },
    359         [_]u32{ 0x00000001, 0x0747AE14, 0x00000000 },
    360         [_]u32{ 0x00000001, 0x7FFFFFFF, 0x00000000 },
    361         [_]u32{ 0x00000001, 0x80000000, 0x00000000 },
    362         [_]u32{ 0x00000001, 0xFFFFFFFD, 0x00000000 },
    363         [_]u32{ 0x00000001, 0xFFFFFFFE, 0x00000000 },
    364         [_]u32{ 0x00000001, 0xFFFFFFFF, 0x00000000 },
    365         [_]u32{ 0x00000002, 0x00000001, 0x00000002 },
    366         [_]u32{ 0x00000002, 0x00000002, 0x00000001 },
    367         [_]u32{ 0x00000002, 0x00000003, 0x00000000 },
    368         [_]u32{ 0x00000002, 0x00000010, 0x00000000 },
    369         [_]u32{ 0x00000002, 0x078644FA, 0x00000000 },
    370         [_]u32{ 0x00000002, 0x0747AE14, 0x00000000 },
    371         [_]u32{ 0x00000002, 0x7FFFFFFF, 0x00000000 },
    372         [_]u32{ 0x00000002, 0x80000000, 0x00000000 },
    373         [_]u32{ 0x00000002, 0xFFFFFFFD, 0x00000000 },
    374         [_]u32{ 0x00000002, 0xFFFFFFFE, 0x00000000 },
    375         [_]u32{ 0x00000002, 0xFFFFFFFF, 0x00000000 },
    376         [_]u32{ 0x00000003, 0x00000001, 0x00000003 },
    377         [_]u32{ 0x00000003, 0x00000002, 0x00000001 },
    378         [_]u32{ 0x00000003, 0x00000003, 0x00000001 },
    379         [_]u32{ 0x00000003, 0x00000010, 0x00000000 },
    380         [_]u32{ 0x00000003, 0x078644FA, 0x00000000 },
    381         [_]u32{ 0x00000003, 0x0747AE14, 0x00000000 },
    382         [_]u32{ 0x00000003, 0x7FFFFFFF, 0x00000000 },
    383         [_]u32{ 0x00000003, 0x80000000, 0x00000000 },
    384         [_]u32{ 0x00000003, 0xFFFFFFFD, 0x00000000 },
    385         [_]u32{ 0x00000003, 0xFFFFFFFE, 0x00000000 },
    386         [_]u32{ 0x00000003, 0xFFFFFFFF, 0x00000000 },
    387         [_]u32{ 0x00000010, 0x00000001, 0x00000010 },
    388         [_]u32{ 0x00000010, 0x00000002, 0x00000008 },
    389         [_]u32{ 0x00000010, 0x00000003, 0x00000005 },
    390         [_]u32{ 0x00000010, 0x00000010, 0x00000001 },
    391         [_]u32{ 0x00000010, 0x078644FA, 0x00000000 },
    392         [_]u32{ 0x00000010, 0x0747AE14, 0x00000000 },
    393         [_]u32{ 0x00000010, 0x7FFFFFFF, 0x00000000 },
    394         [_]u32{ 0x00000010, 0x80000000, 0x00000000 },
    395         [_]u32{ 0x00000010, 0xFFFFFFFD, 0x00000000 },
    396         [_]u32{ 0x00000010, 0xFFFFFFFE, 0x00000000 },
    397         [_]u32{ 0x00000010, 0xFFFFFFFF, 0x00000000 },
    398         [_]u32{ 0x078644FA, 0x00000001, 0x078644FA },
    399         [_]u32{ 0x078644FA, 0x00000002, 0x03C3227D },
    400         [_]u32{ 0x078644FA, 0x00000003, 0x028216FE },
    401         [_]u32{ 0x078644FA, 0x00000010, 0x0078644F },
    402         [_]u32{ 0x078644FA, 0x078644FA, 0x00000001 },
    403         [_]u32{ 0x078644FA, 0x0747AE14, 0x00000001 },
    404         [_]u32{ 0x078644FA, 0x7FFFFFFF, 0x00000000 },
    405         [_]u32{ 0x078644FA, 0x80000000, 0x00000000 },
    406         [_]u32{ 0x078644FA, 0xFFFFFFFD, 0x00000000 },
    407         [_]u32{ 0x078644FA, 0xFFFFFFFE, 0x00000000 },
    408         [_]u32{ 0x078644FA, 0xFFFFFFFF, 0x00000000 },
    409         [_]u32{ 0x0747AE14, 0x00000001, 0x0747AE14 },
    410         [_]u32{ 0x0747AE14, 0x00000002, 0x03A3D70A },
    411         [_]u32{ 0x0747AE14, 0x00000003, 0x026D3A06 },
    412         [_]u32{ 0x0747AE14, 0x00000010, 0x00747AE1 },
    413         [_]u32{ 0x0747AE14, 0x078644FA, 0x00000000 },
    414         [_]u32{ 0x0747AE14, 0x0747AE14, 0x00000001 },
    415         [_]u32{ 0x0747AE14, 0x7FFFFFFF, 0x00000000 },
    416         [_]u32{ 0x0747AE14, 0x80000000, 0x00000000 },
    417         [_]u32{ 0x0747AE14, 0xFFFFFFFD, 0x00000000 },
    418         [_]u32{ 0x0747AE14, 0xFFFFFFFE, 0x00000000 },
    419         [_]u32{ 0x0747AE14, 0xFFFFFFFF, 0x00000000 },
    420         [_]u32{ 0x7FFFFFFF, 0x00000001, 0x7FFFFFFF },
    421         [_]u32{ 0x7FFFFFFF, 0x00000002, 0x3FFFFFFF },
    422         [_]u32{ 0x7FFFFFFF, 0x00000003, 0x2AAAAAAA },
    423         [_]u32{ 0x7FFFFFFF, 0x00000010, 0x07FFFFFF },
    424         [_]u32{ 0x7FFFFFFF, 0x078644FA, 0x00000011 },
    425         [_]u32{ 0x7FFFFFFF, 0x0747AE14, 0x00000011 },
    426         [_]u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000001 },
    427         [_]u32{ 0x7FFFFFFF, 0x80000000, 0x00000000 },
    428         [_]u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x00000000 },
    429         [_]u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x00000000 },
    430         [_]u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000 },
    431         [_]u32{ 0x80000000, 0x00000001, 0x80000000 },
    432         [_]u32{ 0x80000000, 0x00000002, 0x40000000 },
    433         [_]u32{ 0x80000000, 0x00000003, 0x2AAAAAAA },
    434         [_]u32{ 0x80000000, 0x00000010, 0x08000000 },
    435         [_]u32{ 0x80000000, 0x078644FA, 0x00000011 },
    436         [_]u32{ 0x80000000, 0x0747AE14, 0x00000011 },
    437         [_]u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 },
    438         [_]u32{ 0x80000000, 0x80000000, 0x00000001 },
    439         [_]u32{ 0x80000000, 0xFFFFFFFD, 0x00000000 },
    440         [_]u32{ 0x80000000, 0xFFFFFFFE, 0x00000000 },
    441         [_]u32{ 0x80000000, 0xFFFFFFFF, 0x00000000 },
    442         [_]u32{ 0xFFFFFFFD, 0x00000001, 0xFFFFFFFD },
    443         [_]u32{ 0xFFFFFFFD, 0x00000002, 0x7FFFFFFE },
    444         [_]u32{ 0xFFFFFFFD, 0x00000003, 0x55555554 },
    445         [_]u32{ 0xFFFFFFFD, 0x00000010, 0x0FFFFFFF },
    446         [_]u32{ 0xFFFFFFFD, 0x078644FA, 0x00000022 },
    447         [_]u32{ 0xFFFFFFFD, 0x0747AE14, 0x00000023 },
    448         [_]u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x00000001 },
    449         [_]u32{ 0xFFFFFFFD, 0x80000000, 0x00000001 },
    450         [_]u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000001 },
    451         [_]u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0x00000000 },
    452         [_]u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0x00000000 },
    453         [_]u32{ 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE },
    454         [_]u32{ 0xFFFFFFFE, 0x00000002, 0x7FFFFFFF },
    455         [_]u32{ 0xFFFFFFFE, 0x00000003, 0x55555554 },
    456         [_]u32{ 0xFFFFFFFE, 0x00000010, 0x0FFFFFFF },
    457         [_]u32{ 0xFFFFFFFE, 0x078644FA, 0x00000022 },
    458         [_]u32{ 0xFFFFFFFE, 0x0747AE14, 0x00000023 },
    459         [_]u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000002 },
    460         [_]u32{ 0xFFFFFFFE, 0x80000000, 0x00000001 },
    461         [_]u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 },
    462         [_]u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000001 },
    463         [_]u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000 },
    464         [_]u32{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF },
    465         [_]u32{ 0xFFFFFFFF, 0x00000002, 0x7FFFFFFF },
    466         [_]u32{ 0xFFFFFFFF, 0x00000003, 0x55555555 },
    467         [_]u32{ 0xFFFFFFFF, 0x00000010, 0x0FFFFFFF },
    468         [_]u32{ 0xFFFFFFFF, 0x078644FA, 0x00000022 },
    469         [_]u32{ 0xFFFFFFFF, 0x0747AE14, 0x00000023 },
    470         [_]u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000002 },
    471         [_]u32{ 0xFFFFFFFF, 0x80000000, 0x00000001 },
    472         [_]u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000001 },
    473         [_]u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 },
    474         [_]u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 },
    475     };
    476 
    477     for (cases) |case| {
    478         try test_one_udivsi3(case[0], case[1], case[2]);
    479     }
    480 }
    481 
    482 fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {
    483     const q: u32 = __udivsi3(a, b);
    484     try testing.expect(q == expected_q);
    485 }
    486 
    487 pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 {
    488     return n -% __divsi3(n, d) * d;
    489 }
    490 
    491 test "test_modsi3" {
    492     const cases = [_][3]i32{
    493         [_]i32{ 0, 1, 0 },
    494         [_]i32{ 0, -1, 0 },
    495         [_]i32{ 5, 3, 2 },
    496         [_]i32{ 5, -3, 2 },
    497         [_]i32{ -5, 3, -2 },
    498         [_]i32{ -5, -3, -2 },
    499         [_]i32{ @bitCast(@as(u32, @intCast(0x80000000))), 1, 0x0 },
    500         [_]i32{ @bitCast(@as(u32, @intCast(0x80000000))), 2, 0x0 },
    501         [_]i32{ @bitCast(@as(u32, @intCast(0x80000000))), -2, 0x0 },
    502         [_]i32{ @bitCast(@as(u32, @intCast(0x80000000))), 3, -2 },
    503         [_]i32{ @bitCast(@as(u32, @intCast(0x80000000))), -3, -2 },
    504     };
    505 
    506     for (cases) |case| {
    507         try test_one_modsi3(case[0], case[1], case[2]);
    508     }
    509 }
    510 
    511 fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {
    512     const r: i32 = __modsi3(a, b);
    513     try testing.expect(r == expected_r);
    514 }
    515 
    516 pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 {
    517     return n -% __udivsi3(n, d) * d;
    518 }
    519 
    520 test "test_umodsi3" {
    521     const cases = [_][3]u32{
    522         [_]u32{ 0x00000000, 0x00000001, 0x00000000 },
    523         [_]u32{ 0x00000000, 0x00000002, 0x00000000 },
    524         [_]u32{ 0x00000000, 0x00000003, 0x00000000 },
    525         [_]u32{ 0x00000000, 0x00000010, 0x00000000 },
    526         [_]u32{ 0x00000000, 0x078644FA, 0x00000000 },
    527         [_]u32{ 0x00000000, 0x0747AE14, 0x00000000 },
    528         [_]u32{ 0x00000000, 0x7FFFFFFF, 0x00000000 },
    529         [_]u32{ 0x00000000, 0x80000000, 0x00000000 },
    530         [_]u32{ 0x00000000, 0xFFFFFFFD, 0x00000000 },
    531         [_]u32{ 0x00000000, 0xFFFFFFFE, 0x00000000 },
    532         [_]u32{ 0x00000000, 0xFFFFFFFF, 0x00000000 },
    533         [_]u32{ 0x00000001, 0x00000001, 0x00000000 },
    534         [_]u32{ 0x00000001, 0x00000002, 0x00000001 },
    535         [_]u32{ 0x00000001, 0x00000003, 0x00000001 },
    536         [_]u32{ 0x00000001, 0x00000010, 0x00000001 },
    537         [_]u32{ 0x00000001, 0x078644FA, 0x00000001 },
    538         [_]u32{ 0x00000001, 0x0747AE14, 0x00000001 },
    539         [_]u32{ 0x00000001, 0x7FFFFFFF, 0x00000001 },
    540         [_]u32{ 0x00000001, 0x80000000, 0x00000001 },
    541         [_]u32{ 0x00000001, 0xFFFFFFFD, 0x00000001 },
    542         [_]u32{ 0x00000001, 0xFFFFFFFE, 0x00000001 },
    543         [_]u32{ 0x00000001, 0xFFFFFFFF, 0x00000001 },
    544         [_]u32{ 0x00000002, 0x00000001, 0x00000000 },
    545         [_]u32{ 0x00000002, 0x00000002, 0x00000000 },
    546         [_]u32{ 0x00000002, 0x00000003, 0x00000002 },
    547         [_]u32{ 0x00000002, 0x00000010, 0x00000002 },
    548         [_]u32{ 0x00000002, 0x078644FA, 0x00000002 },
    549         [_]u32{ 0x00000002, 0x0747AE14, 0x00000002 },
    550         [_]u32{ 0x00000002, 0x7FFFFFFF, 0x00000002 },
    551         [_]u32{ 0x00000002, 0x80000000, 0x00000002 },
    552         [_]u32{ 0x00000002, 0xFFFFFFFD, 0x00000002 },
    553         [_]u32{ 0x00000002, 0xFFFFFFFE, 0x00000002 },
    554         [_]u32{ 0x00000002, 0xFFFFFFFF, 0x00000002 },
    555         [_]u32{ 0x00000003, 0x00000001, 0x00000000 },
    556         [_]u32{ 0x00000003, 0x00000002, 0x00000001 },
    557         [_]u32{ 0x00000003, 0x00000003, 0x00000000 },
    558         [_]u32{ 0x00000003, 0x00000010, 0x00000003 },
    559         [_]u32{ 0x00000003, 0x078644FA, 0x00000003 },
    560         [_]u32{ 0x00000003, 0x0747AE14, 0x00000003 },
    561         [_]u32{ 0x00000003, 0x7FFFFFFF, 0x00000003 },
    562         [_]u32{ 0x00000003, 0x80000000, 0x00000003 },
    563         [_]u32{ 0x00000003, 0xFFFFFFFD, 0x00000003 },
    564         [_]u32{ 0x00000003, 0xFFFFFFFE, 0x00000003 },
    565         [_]u32{ 0x00000003, 0xFFFFFFFF, 0x00000003 },
    566         [_]u32{ 0x00000010, 0x00000001, 0x00000000 },
    567         [_]u32{ 0x00000010, 0x00000002, 0x00000000 },
    568         [_]u32{ 0x00000010, 0x00000003, 0x00000001 },
    569         [_]u32{ 0x00000010, 0x00000010, 0x00000000 },
    570         [_]u32{ 0x00000010, 0x078644FA, 0x00000010 },
    571         [_]u32{ 0x00000010, 0x0747AE14, 0x00000010 },
    572         [_]u32{ 0x00000010, 0x7FFFFFFF, 0x00000010 },
    573         [_]u32{ 0x00000010, 0x80000000, 0x00000010 },
    574         [_]u32{ 0x00000010, 0xFFFFFFFD, 0x00000010 },
    575         [_]u32{ 0x00000010, 0xFFFFFFFE, 0x00000010 },
    576         [_]u32{ 0x00000010, 0xFFFFFFFF, 0x00000010 },
    577         [_]u32{ 0x078644FA, 0x00000001, 0x00000000 },
    578         [_]u32{ 0x078644FA, 0x00000002, 0x00000000 },
    579         [_]u32{ 0x078644FA, 0x00000003, 0x00000000 },
    580         [_]u32{ 0x078644FA, 0x00000010, 0x0000000A },
    581         [_]u32{ 0x078644FA, 0x078644FA, 0x00000000 },
    582         [_]u32{ 0x078644FA, 0x0747AE14, 0x003E96E6 },
    583         [_]u32{ 0x078644FA, 0x7FFFFFFF, 0x078644FA },
    584         [_]u32{ 0x078644FA, 0x80000000, 0x078644FA },
    585         [_]u32{ 0x078644FA, 0xFFFFFFFD, 0x078644FA },
    586         [_]u32{ 0x078644FA, 0xFFFFFFFE, 0x078644FA },
    587         [_]u32{ 0x078644FA, 0xFFFFFFFF, 0x078644FA },
    588         [_]u32{ 0x0747AE14, 0x00000001, 0x00000000 },
    589         [_]u32{ 0x0747AE14, 0x00000002, 0x00000000 },
    590         [_]u32{ 0x0747AE14, 0x00000003, 0x00000002 },
    591         [_]u32{ 0x0747AE14, 0x00000010, 0x00000004 },
    592         [_]u32{ 0x0747AE14, 0x078644FA, 0x0747AE14 },
    593         [_]u32{ 0x0747AE14, 0x0747AE14, 0x00000000 },
    594         [_]u32{ 0x0747AE14, 0x7FFFFFFF, 0x0747AE14 },
    595         [_]u32{ 0x0747AE14, 0x80000000, 0x0747AE14 },
    596         [_]u32{ 0x0747AE14, 0xFFFFFFFD, 0x0747AE14 },
    597         [_]u32{ 0x0747AE14, 0xFFFFFFFE, 0x0747AE14 },
    598         [_]u32{ 0x0747AE14, 0xFFFFFFFF, 0x0747AE14 },
    599         [_]u32{ 0x7FFFFFFF, 0x00000001, 0x00000000 },
    600         [_]u32{ 0x7FFFFFFF, 0x00000002, 0x00000001 },
    601         [_]u32{ 0x7FFFFFFF, 0x00000003, 0x00000001 },
    602         [_]u32{ 0x7FFFFFFF, 0x00000010, 0x0000000F },
    603         [_]u32{ 0x7FFFFFFF, 0x078644FA, 0x00156B65 },
    604         [_]u32{ 0x7FFFFFFF, 0x0747AE14, 0x043D70AB },
    605         [_]u32{ 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000 },
    606         [_]u32{ 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF },
    607         [_]u32{ 0x7FFFFFFF, 0xFFFFFFFD, 0x7FFFFFFF },
    608         [_]u32{ 0x7FFFFFFF, 0xFFFFFFFE, 0x7FFFFFFF },
    609         [_]u32{ 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF },
    610         [_]u32{ 0x80000000, 0x00000001, 0x00000000 },
    611         [_]u32{ 0x80000000, 0x00000002, 0x00000000 },
    612         [_]u32{ 0x80000000, 0x00000003, 0x00000002 },
    613         [_]u32{ 0x80000000, 0x00000010, 0x00000000 },
    614         [_]u32{ 0x80000000, 0x078644FA, 0x00156B66 },
    615         [_]u32{ 0x80000000, 0x0747AE14, 0x043D70AC },
    616         [_]u32{ 0x80000000, 0x7FFFFFFF, 0x00000001 },
    617         [_]u32{ 0x80000000, 0x80000000, 0x00000000 },
    618         [_]u32{ 0x80000000, 0xFFFFFFFD, 0x80000000 },
    619         [_]u32{ 0x80000000, 0xFFFFFFFE, 0x80000000 },
    620         [_]u32{ 0x80000000, 0xFFFFFFFF, 0x80000000 },
    621         [_]u32{ 0xFFFFFFFD, 0x00000001, 0x00000000 },
    622         [_]u32{ 0xFFFFFFFD, 0x00000002, 0x00000001 },
    623         [_]u32{ 0xFFFFFFFD, 0x00000003, 0x00000001 },
    624         [_]u32{ 0xFFFFFFFD, 0x00000010, 0x0000000D },
    625         [_]u32{ 0xFFFFFFFD, 0x078644FA, 0x002AD6C9 },
    626         [_]u32{ 0xFFFFFFFD, 0x0747AE14, 0x01333341 },
    627         [_]u32{ 0xFFFFFFFD, 0x7FFFFFFF, 0x7FFFFFFE },
    628         [_]u32{ 0xFFFFFFFD, 0x80000000, 0x7FFFFFFD },
    629         [_]u32{ 0xFFFFFFFD, 0xFFFFFFFD, 0x00000000 },
    630         [_]u32{ 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFD },
    631         [_]u32{ 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFD },
    632         [_]u32{ 0xFFFFFFFE, 0x00000001, 0x00000000 },
    633         [_]u32{ 0xFFFFFFFE, 0x00000002, 0x00000000 },
    634         [_]u32{ 0xFFFFFFFE, 0x00000003, 0x00000002 },
    635         [_]u32{ 0xFFFFFFFE, 0x00000010, 0x0000000E },
    636         [_]u32{ 0xFFFFFFFE, 0x078644FA, 0x002AD6CA },
    637         [_]u32{ 0xFFFFFFFE, 0x0747AE14, 0x01333342 },
    638         [_]u32{ 0xFFFFFFFE, 0x7FFFFFFF, 0x00000000 },
    639         [_]u32{ 0xFFFFFFFE, 0x80000000, 0x7FFFFFFE },
    640         [_]u32{ 0xFFFFFFFE, 0xFFFFFFFD, 0x00000001 },
    641         [_]u32{ 0xFFFFFFFE, 0xFFFFFFFE, 0x00000000 },
    642         [_]u32{ 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE },
    643         [_]u32{ 0xFFFFFFFF, 0x00000001, 0x00000000 },
    644         [_]u32{ 0xFFFFFFFF, 0x00000002, 0x00000001 },
    645         [_]u32{ 0xFFFFFFFF, 0x00000003, 0x00000000 },
    646         [_]u32{ 0xFFFFFFFF, 0x00000010, 0x0000000F },
    647         [_]u32{ 0xFFFFFFFF, 0x078644FA, 0x002AD6CB },
    648         [_]u32{ 0xFFFFFFFF, 0x0747AE14, 0x01333343 },
    649         [_]u32{ 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001 },
    650         [_]u32{ 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF },
    651         [_]u32{ 0xFFFFFFFF, 0xFFFFFFFD, 0x00000002 },
    652         [_]u32{ 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001 },
    653         [_]u32{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
    654     };
    655 
    656     for (cases) |case| {
    657         try test_one_umodsi3(case[0], case[1], case[2]);
    658     }
    659 }
    660 
    661 fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {
    662     const r: u32 = __umodsi3(a, b);
    663     try testing.expect(r == expected_r);
    664 }