Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ int test__aeabi_idivmod(si_int a, si_int b,
{
si_int rem;
du_int ret = __aeabi_idivmod(a, b);
// __aeabi_idivmod actually returns a struct { quotient; remainder; } using
// value_in_regs calling convention. Due to the ABI rules, struct fields
// come in the same order regardless of endianness. However since the
// result is received here as a 64-bit integer, in which endianness does
// matter, the position of each component (quotient and remainder) varies
// depending on endianness.
# if _YUGA_BIG_ENDIAN
rem = ret & 0xFFFFFFFF;
si_int result = ret >> 32;
# else
rem = ret >> 32;
si_int result = ret & 0xFFFFFFFF;
# endif
if (result != expected_result) {
printf("error in __aeabi_idivmod: %d / %d = %d, expected %d\n",
a, b, result, expected_result);
Expand Down
11 changes: 11 additions & 0 deletions compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,19 @@ int test__aeabi_uidivmod(su_int a, su_int b,
su_int expected_result, su_int expected_rem)
{
du_int ret = __aeabi_uidivmod(a, b);
// __aeabi_uidivmod actually returns a struct { quotient; remainder; }
// using value_in_regs calling convention. Due to the ABI rules, struct
// fields come in the same order regardless of endianness. However since
// the result is received here as a 64-bit integer, in which endianness
// does matter, the position of each component (quotient and remainder)
// varies depending on endianness.
# if _YUGA_BIG_ENDIAN
su_int rem = ret & 0xFFFFFFFF;
si_int result = ret >> 32;
# else
su_int rem = ret >> 32;
si_int result = ret & 0xFFFFFFFF;
# endif

if (result != expected_result) {
printf("error in __aeabi_uidivmod: %u / %u = %u, expected %u\n",
Expand Down
23 changes: 20 additions & 3 deletions compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,37 @@ COMPILER_RT_ABI void /* __value_in_regs */ __aeabi_uldivmod(du_int a, du_int b);
int test_aeabi_uldivmod(du_int a, du_int b, du_int expected_q, du_int expected_r)
{
du_int q, r;
// __aeabi_uldivmod returns a struct { quotient; remainder; } using
// value_in_regs calling convention. Each field is a 64-bit integer, so the
// quotient resides in r0 and r1, while the remainder in r2 and r3. The
// byte order however depends on the endianness.
__asm__(
# if _YUGA_BIG_ENDIAN
"movs r1, %Q[a] \n"
"movs r0, %R[a] \n"
"movs r3, %Q[b] \n"
"movs r2, %R[b] \n"
# else
"movs r0, %Q[a] \n"
"movs r1, %R[a] \n"
"movs r2, %Q[b] \n"
"movs r3, %R[b] \n"
# endif
"bl __aeabi_uldivmod \n"
# if _YUGA_BIG_ENDIAN
"movs %Q[q], r1\n"
"movs %R[q], r0\n"
"movs %Q[r], r3\n"
"movs %R[r], r2\n"
# else
"movs %Q[q], r0\n"
"movs %R[q], r1\n"
"movs %Q[r], r2\n"
"movs %R[r], r3\n"
: [q] "=r" (q), [r] "=r"(r)
# endif
: [q] "=r"(q), [r] "=r"(r)
: [a] "r"(a), [b] "r"(b)
: "lr", "r0", "r1", "r2", "r3"
);
: "lr", "r0", "r1", "r2", "r3");
if (q != expected_q || r != expected_r)
printf("error in aeabi_uldivmod: %llX / %llX = %llX, R = %llX, expected %llX, %llX\n",
a, b, q, r, expected_q, expected_r);
Expand Down