master
  1//! Builtin functions that operate on integer types
  2
  3const builtin = @import("builtin");
  4const std = @import("std");
  5const testing = std.testing;
  6const maxInt = std.math.maxInt;
  7const minInt = std.math.minInt;
  8const arch = builtin.cpu.arch;
  9const common = @import("common.zig");
 10const udivmod = @import("udivmod.zig").udivmod;
 11const __divti3 = @import("divti3.zig").__divti3;
 12
 13pub const panic = common.panic;
 14
 15comptime {
 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
 36pub 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
 42test "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
 63fn 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
 69pub 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
 75fn 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
 81const 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
 97test "test_divmoddi4" {
 98    for (cases__divmoddi4) |case| {
 99        try test_one_divmoddi4(case[0], case[1], case[2], case[3]);
100    }
101}
102
103pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 {
104    return udivmod(u64, a, b, maybe_rem);
105}
106
107test "test_udivmoddi4" {
108    _ = @import("udivmoddi4_test.zig");
109}
110
111pub 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
123test "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
143fn 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
148pub 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
159test "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
181fn 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
186pub fn __udivdi3(a: u64, b: u64) callconv(.c) u64 {
187    return __udivmoddi4(a, b, null);
188}
189
190pub fn __umoddi3(a: u64, b: u64) callconv(.c) u64 {
191    var r: u64 = undefined;
192    _ = __udivmoddi4(a, b, &r);
193    return r;
194}
195
196test "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
204fn 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
209pub 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
215const 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
231fn 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
237test "test_divmodsi4" {
238    for (cases__divmodsi4) |case| {
239        try test_one_divmodsi4(case[0], case[1], case[2], case[3]);
240    }
241}
242
243pub 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
249pub fn __divsi3(n: i32, d: i32) callconv(.c) i32 {
250    return div_i32(n, d);
251}
252
253fn __aeabi_idiv(n: i32, d: i32) callconv(.{ .arm_aapcs = .{} }) i32 {
254    return div_i32(n, d);
255}
256
257inline 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
269test "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
289fn 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
294pub fn __udivsi3(n: u32, d: u32) callconv(.c) u32 {
295    return div_u32(n, d);
296}
297
298fn __aeabi_uidiv(n: u32, d: u32) callconv(.{ .arm_aapcs = .{} }) u32 {
299    return div_u32(n, d);
300}
301
302inline 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
341test "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
482fn 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
487pub fn __modsi3(n: i32, d: i32) callconv(.c) i32 {
488    return n -% __divsi3(n, d) * d;
489}
490
491test "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
511fn 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
516pub fn __umodsi3(n: u32, d: u32) callconv(.c) u32 {
517    return n -% __udivsi3(n, d) * d;
518}
519
520test "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
661fn 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}