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}