From dd99a15df4556e310dde0966ccdcdbfce5b0ae9e Mon Sep 17 00:00:00 2001 From: Victor Campos Date: Fri, 7 Feb 2025 17:35:59 +0000 Subject: [PATCH 1/4] [compiler-rt] Add big endian support to __aeabi_(idivmod|uidivmod|uldivmod) This patch makes these functions work in big endian mode: - `__aeabi_idivmod`. - `__aeabi_uidivmod`. The `__aeabi_uldivmod` function was already compatible with big endian, but its test was not. So in this case, only the test needed fixing. --- compiler-rt/lib/builtins/arm/aeabi_idivmod.S | 5 +++++ compiler-rt/lib/builtins/arm/aeabi_uidivmod.S | 5 +++++ .../test/builtins/Unit/arm/aeabi_uldivmod_test.c | 14 ++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/compiler-rt/lib/builtins/arm/aeabi_idivmod.S b/compiler-rt/lib/builtins/arm/aeabi_idivmod.S index bb80e4b96fc1a..b08f773e86483 100644 --- a/compiler-rt/lib/builtins/arm/aeabi_idivmod.S +++ b/compiler-rt/lib/builtins/arm/aeabi_idivmod.S @@ -40,7 +40,12 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) mov r1, r3 #endif bl SYMBOL_NAME(__divmodsi4) +#if _YUGA_BIG_ENDIAN + mov r1, r0 + ldr r0, [sp] +#else ldr r1, [sp] +#endif add sp, sp, #4 pop { pc } #endif // defined(USE_THUMB_1) diff --git a/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S b/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S index df030769fd40b..dc3cf90496c59 100644 --- a/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S +++ b/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S @@ -47,7 +47,12 @@ LOCAL_LABEL(case_denom_larger): mov r1, r3 #endif bl SYMBOL_NAME(__udivmodsi4) +#if _YUGA_BIG_ENDIAN + mov r1, r0 + ldr r0, [sp] +#else ldr r1, [sp] +#endif add sp, sp, #4 pop { pc } #endif diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c index 2ff65a8b9ec3f..32b08d60484c7 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c @@ -13,15 +13,29 @@ int test_aeabi_uldivmod(du_int a, du_int b, du_int expected_q, du_int expected_r { du_int q, r; __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" +#endif : [q] "=r" (q), [r] "=r"(r) : [a] "r"(a), [b] "r"(b) : "lr", "r0", "r1", "r2", "r3" From aa280c91cf741f83a15f2c9ebd0ba8a1aa672ff9 Mon Sep 17 00:00:00 2001 From: Victor Campos Date: Fri, 7 Feb 2025 17:53:43 +0000 Subject: [PATCH 2/4] Fix clang-format --- .../builtins/Unit/arm/aeabi_uldivmod_test.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c index 32b08d60484c7..695f50fe2586b 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c @@ -13,33 +13,32 @@ int test_aeabi_uldivmod(du_int a, du_int b, du_int expected_q, du_int expected_r { du_int q, r; __asm__( -#if _YUGA_BIG_ENDIAN +# 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 +# else "movs r0, %Q[a] \n" "movs r1, %R[a] \n" "movs r2, %Q[b] \n" "movs r3, %R[b] \n" -#endif +# endif "bl __aeabi_uldivmod \n" -#if _YUGA_BIG_ENDIAN +# 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 +# else "movs %Q[q], r0\n" "movs %R[q], r1\n" "movs %Q[r], r2\n" "movs %R[r], r3\n" -#endif - : [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); From 16d863d1a9df3a8938a7429500d0e03f1b8fdd40 Mon Sep 17 00:00:00 2001 From: Victor Campos Date: Mon, 10 Feb 2025 13:28:06 +0000 Subject: [PATCH 3/4] Changes to the tests. Revert changes to implementation --- compiler-rt/lib/builtins/arm/aeabi_idivmod.S | 5 ----- compiler-rt/lib/builtins/arm/aeabi_uidivmod.S | 5 ----- compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c | 5 +++++ compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c | 5 +++++ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler-rt/lib/builtins/arm/aeabi_idivmod.S b/compiler-rt/lib/builtins/arm/aeabi_idivmod.S index b08f773e86483..bb80e4b96fc1a 100644 --- a/compiler-rt/lib/builtins/arm/aeabi_idivmod.S +++ b/compiler-rt/lib/builtins/arm/aeabi_idivmod.S @@ -40,12 +40,7 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) mov r1, r3 #endif bl SYMBOL_NAME(__divmodsi4) -#if _YUGA_BIG_ENDIAN - mov r1, r0 - ldr r0, [sp] -#else ldr r1, [sp] -#endif add sp, sp, #4 pop { pc } #endif // defined(USE_THUMB_1) diff --git a/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S b/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S index dc3cf90496c59..df030769fd40b 100644 --- a/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S +++ b/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S @@ -47,12 +47,7 @@ LOCAL_LABEL(case_denom_larger): mov r1, r3 #endif bl SYMBOL_NAME(__udivmodsi4) -#if _YUGA_BIG_ENDIAN - mov r1, r0 - ldr r0, [sp] -#else ldr r1, [sp] -#endif add sp, sp, #4 pop { pc } #endif diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c index ff767d754eb97..e5b10d39c89cb 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c @@ -14,8 +14,13 @@ int test__aeabi_idivmod(si_int a, si_int b, { si_int rem; du_int ret = __aeabi_idivmod(a, b); +# 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); diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c index de5a43d5b8143..fd5fce159fd81 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c @@ -13,8 +13,13 @@ 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); +# 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", From 66d28e3cf8824f67251484b4ef5125521da6fc66 Mon Sep 17 00:00:00 2001 From: Victor Campos Date: Mon, 10 Feb 2025 16:07:55 +0000 Subject: [PATCH 4/4] Added code comments for clarification --- compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c | 6 ++++++ compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c | 6 ++++++ compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c index e5b10d39c89cb..e4953bf51b037 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_idivmod_test.c @@ -14,6 +14,12 @@ 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; diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c index fd5fce159fd81..a507267c44602 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_uidivmod_test.c @@ -13,6 +13,12 @@ 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; diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c index 695f50fe2586b..02cfa2f38713b 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c @@ -12,6 +12,10 @@ 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"