Merge pull request #2372 from LemonBoy/aeabi_idiv

compiler-rt: Add __divsi3, __aeabi_idiv
master
Andrew Kelley 2019-04-29 18:54:21 -04:00 committed by GitHub
commit d2328ac71a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 81 additions and 1 deletions

View File

@ -102,9 +102,11 @@ comptime {
@export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage);
@export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage);
@export("__divsi3", __divsi3, linkage);
@export("__udivsi3", __udivsi3, linkage);
@export("__udivdi3", __udivdi3, linkage);
@export("__umoddi3", __umoddi3, linkage);
@export("__divmodsi4", __divmodsi4, linkage);
@export("__udivmodsi4", __udivmodsi4, linkage);
@export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
@ -112,8 +114,11 @@ comptime {
if (is_arm_arch and !is_arm_64) {
@export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
@export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
@export("__aeabi_idiv", __divsi3, linkage);
@export("__aeabi_idivmod", __divmodsi4, linkage);
@export("__aeabi_uidiv", __udivsi3, linkage);
@export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
@export("__aeabi_memcpy", __aeabi_memcpy, linkage);
@export("__aeabi_memcpy4", __aeabi_memcpy, linkage);
@ -558,6 +563,14 @@ nakedcc fn ___chkstk_ms() align(4) void {
);
}
extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 {
@setRuntimeSafety(is_test);
const d = __divsi3(a, b);
rem.* = a -% (d * b);
return d;
}
extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
@setRuntimeSafety(is_test);
@ -566,6 +579,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
return d;
}
extern fn __divsi3(n: i32, d: i32) i32 {
@setRuntimeSafety(is_test);
// Set aside the sign of the quotient.
const sign = @bitCast(u32, (n ^ d) >> 31);
// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
const abs_n = (n ^ (n >> 31)) -% (n >> 31);
const abs_d = (d ^ (d >> 31)) -% (d >> 31);
// abs(a) / abs(b)
const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d);
// Apply sign of quotient to result and return.
return @bitCast(i32, (res ^ sign) -% sign);
}
extern fn __udivsi3(n: u32, d: u32) u32 {
@setRuntimeSafety(is_test);
@ -1293,3 +1320,56 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {
const q: u32 = __udivsi3(a, b);
testing.expect(q == expected_q);
}
test "test_divsi3" {
const cases = [][3]i32{
[]i32{ 0, 1, 0},
[]i32{ 0, -1, 0},
[]i32{ 2, 1, 2},
[]i32{ 2, -1, -2},
[]i32{-2, 1, -2},
[]i32{-2, -1, 2},
[]i32{@bitCast(i32, u32(0x80000000)), 1, @bitCast(i32, u32(0x80000000))},
[]i32{@bitCast(i32, u32(0x80000000)), -1, @bitCast(i32, u32(0x80000000))},
[]i32{@bitCast(i32, u32(0x80000000)), -2, 0x40000000},
[]i32{@bitCast(i32, u32(0x80000000)), 2, @bitCast(i32, u32(0xC0000000))},
};
for (cases) |case| {
test_one_divsi3(case[0], case[1], case[2]);
}
}
fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void {
const q: i32 = __divsi3(a, b);
testing.expect(q == expected_q);
}
test "test_divmodsi4" {
const cases = [][4]i32{
[]i32{ 0, 1, 0, 0},
[]i32{ 0, -1, 0, 0},
[]i32{ 2, 1, 2, 0},
[]i32{ 2, -1, -2, 0},
[]i32{-2, 1, -2, 0},
[]i32{-2, -1, 2, 0},
[]i32{ 7, 5, 1, 2},
[]i32{-7, 5, -1, -2},
[]i32{19, 5, 3, 4},
[]i32{19, -5, -3, 4},
[]i32{@bitCast(i32, u32(0x80000000)), 8, @bitCast(i32, u32(0xf0000000)), 0},
[]i32{@bitCast(i32, u32(0x80000007)), 8, @bitCast(i32, u32(0xf0000001)), -1},
};
for (cases) |case| {
test_one_divmodsi4(case[0], case[1], case[2], case[3]);
}
}
fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void {
var r: i32 = undefined;
const q: i32 = __divmodsi4(a, b, &r);
testing.expect(q == expected_q and r == expected_r);
}