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