diff --git a/reactos/lib/sdk/crt/crt.cmake b/reactos/lib/sdk/crt/crt.cmake index 3be45a5411a..d9c7a60a32d 100644 --- a/reactos/lib/sdk/crt/crt.cmake +++ b/reactos/lib/sdk/crt/crt.cmake @@ -476,7 +476,10 @@ elseif(ARCH STREQUAL "amd64") endif() elseif(ARCH STREQUAL "arm") list(APPEND LIBCNTPR_SOURCE - math/arm/__rt_div.c + math/arm/__rt_sdiv.c + math/arm/__rt_sdiv64_worker.c + math/arm/__rt_udiv.c + math/arm/__rt_udiv64_worker.c ) list(APPEND CRT_ASM_SOURCE math/arm/floor.s diff --git a/reactos/lib/sdk/crt/libcntpr.cmake b/reactos/lib/sdk/crt/libcntpr.cmake index 95df115ea9e..d96979036ee 100644 --- a/reactos/lib/sdk/crt/libcntpr.cmake +++ b/reactos/lib/sdk/crt/libcntpr.cmake @@ -135,7 +135,10 @@ elseif(ARCH STREQUAL "amd64") math/sin.c) elseif(ARCH STREQUAL "arm") list(APPEND LIBCNTPR_SOURCE - math/arm/__rt_div.c + math/arm/__rt_sdiv.c + math/arm/__rt_sdiv64_worker.c + math/arm/__rt_udiv.c + math/arm/__rt_udiv64_worker.c ) list(APPEND LIBCNTPR_ASM_SOURCE math/arm/floor.s diff --git a/reactos/lib/sdk/crt/math/arm/__rt_div_worker.h b/reactos/lib/sdk/crt/math/arm/__rt_div_worker.h new file mode 100644 index 00000000000..78bf31d568f --- /dev/null +++ b/reactos/lib/sdk/crt/math/arm/__rt_div_worker.h @@ -0,0 +1,116 @@ +/* + * COPYRIGHT: BSD, see COPYING.ARM in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/math/arm/__rt_udiv.c + * PURPOSE: Implementation of __rt_udiv + * PROGRAMMER: Timo Kreuzer + * REFERENCE: http://research.microsoft.com/pubs/70645/tr-2008-141.pdf + * http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_div10.s.htm + * http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_udiv.c.htm + */ + +#ifdef _USE_64_BITS_ +typedef unsigned long long UINT3264; +typedef long long INT3264; +#define _CountLeadingZeros _CountLeadingZeros64 +#else +typedef unsigned int UINT3264; +typedef int INT3264; +#endif + +__forceinline +void +__brkdiv0(void) +{ + __emit(0xDEF9); +} + +typedef struct _ARM_DIVRESULT +{ + UINT3264 quotient; /* to be returned in R0 */ + UINT3264 modulus; /* to be returned in R1 */ +} ARM_DIVRESULT; + +#ifndef _USE_64_BITS_ +__forceinline +#endif +void +__rt_div_worker( + ARM_DIVRESULT *result, + UINT3264 divisor, + UINT3264 dividend) +{ + UINT3264 shift; + UINT3264 mask; + UINT3264 quotient; +#ifdef _SIGNED_DIV_ + int dividend_sign; + int divisor_sign; +#endif // _SIGNED_DIV_ + + if (divisor == 0) + { + /* Raise divide by zero error */ + __brkdiv0(); + } + +#ifdef _SIGNED_DIV_ + if ((INT3264)dividend < 0) + { + dividend_sign = 1; + dividend = -(INT3264)dividend; + } + + if ((INT3264)divisor < 0) + { + divisor_sign = 1; + divisor = -(INT3264)divisor; + } +#endif // _SIGNED_DIV_ + + if (divisor > dividend) + { + result->quotient = 0; + result->modulus = divisor; + return; + } + + /* Get the difference in count of leading zeros between dividend and divisor */ + shift = _CountLeadingZeros(divisor); + shift -= _CountLeadingZeros(dividend); + + /* Shift the divisor to the left, so that it's highest bit is the same + as the highest bit of the dividend */ + divisor <<= shift; + + mask = (UINT3264)1 << shift; + + quotient = 0; + do + { + if (dividend >= divisor) + { + quotient |= mask; + dividend -= divisor; + } + divisor >>= 1; + mask >>= 1; + } + while (mask); + +#ifdef _SIGNED_DIV_ + if (dividend_sign ^ divisor_sign) + { + quotient = -(INT3264)quotient; + } + + if (dividend_sign) + { + dividend = -(INT3264)dividend; + } +#endif // _SIGNED_DIV_ + + result->quotient = quotient; + result->modulus = dividend; + return; +} diff --git a/reactos/lib/sdk/crt/math/arm/__rt_sdiv.c b/reactos/lib/sdk/crt/math/arm/__rt_sdiv.c new file mode 100644 index 00000000000..28906feccbc --- /dev/null +++ b/reactos/lib/sdk/crt/math/arm/__rt_sdiv.c @@ -0,0 +1,26 @@ +/* + * COPYRIGHT: BSD, see COPYING.ARM in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/math/arm/__rt_sdiv.c + * PURPOSE: Implementation of __rt_sdiv + * PROGRAMMER: Timo Kreuzer + * REFERENCE: http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_div10.s.htm + * http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_udiv.c.htm + */ + +#define __rt_div_worker __rt_sdiv_worker +#define _SIGNED_DIV_ + +#include "__rt_div_worker.h" + +ARM_DIVRESULT +__rt_sdiv( + int divisor, + int dividend) +{ + ARM_DIVRESULT result; + + __rt_sdiv_worker(&result, divisor, dividend); + return result; +} + diff --git a/reactos/lib/sdk/crt/math/arm/__rt_sdiv64.s b/reactos/lib/sdk/crt/math/arm/__rt_sdiv64.s index c6167831ec9..426ea366717 100644 --- a/reactos/lib/sdk/crt/math/arm/__rt_sdiv64.s +++ b/reactos/lib/sdk/crt/math/arm/__rt_sdiv64.s @@ -9,12 +9,28 @@ #include + IMPORT __rt_sdiv64_worker + /* CODE **********************************************************************/ TEXTAREA - LEAF_ENTRY __rt_sdiv64 + NESTED_ENTRY __rt_sdiv64 - LEAF_END __rt_sdiv64 + /* Allocate stack space and store parameters there */ + stmdb sp!,{r0,r1,r2,r3,lr} + PROLOG_END + + /* Load pointer to stack structure into R0 */ + mov r0, sp + + /* Call the C worker function */ + adr lr, Return + b __rt_sdiv64_worker + +Return + /* Move result data into the appropriate registers and return */ + ldmia sp!,{r0,r1,r2,r3,pc} + ENTRY_END __rt_sdiv64 END /* EOF */ diff --git a/reactos/lib/sdk/crt/math/arm/__rt_sdiv64_worker.c b/reactos/lib/sdk/crt/math/arm/__rt_sdiv64_worker.c new file mode 100644 index 00000000000..970df72f0f3 --- /dev/null +++ b/reactos/lib/sdk/crt/math/arm/__rt_sdiv64_worker.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: BSD, see COPYING.ARM in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/math/arm/__rt_sdiv_worker.c + * PURPOSE: Implementation of __rt_sdiv_worker + * PROGRAMMER: Timo Kreuzer + * REFERENCE: http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_div10.s.htm + * http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_udiv.c.htm + */ + +#define __rt_div_worker __rt_sdiv64_worker +#define _SIGNED_DIV_ +#define _USE_64_BITS_ + +#include "__rt_div_worker.h" + +/* __rt_sdiv64 is implemented in __rt_sdiv64.s */ diff --git a/reactos/lib/sdk/crt/math/arm/__rt_udiv.c b/reactos/lib/sdk/crt/math/arm/__rt_udiv.c new file mode 100644 index 00000000000..29c4df49bd0 --- /dev/null +++ b/reactos/lib/sdk/crt/math/arm/__rt_udiv.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: BSD, see COPYING.ARM in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/math/arm/__rt_udiv.c + * PURPOSE: Implementation of __rt_udiv + * PROGRAMMER: Timo Kreuzer + * REFERENCE: http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_div10.s.htm + * http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_udiv.c.htm + */ + +#define __rt_div_worker __rt_udiv_worker + +#include "__rt_div_worker.h" + +ARM_DIVRESULT +__rt_udiv( + unsigned int divisor, + unsigned int dividend) +{ + ARM_DIVRESULT result; + + __rt_udiv_worker(&result, divisor, dividend); + return result; +} + diff --git a/reactos/lib/sdk/crt/math/arm/__rt_udiv64.s b/reactos/lib/sdk/crt/math/arm/__rt_udiv64.s index 3c7e8acb295..81d39e32d19 100644 --- a/reactos/lib/sdk/crt/math/arm/__rt_udiv64.s +++ b/reactos/lib/sdk/crt/math/arm/__rt_udiv64.s @@ -9,12 +9,28 @@ #include + IMPORT __rt_udiv64_worker + /* CODE **********************************************************************/ TEXTAREA - LEAF_ENTRY __rt_udiv64 + NESTED_ENTRY __rt_udiv64 - LEAF_END __rt_udiv64 + /* Allocate stack space and store parameters there */ + stmdb sp!,{r0,r1,r2,r3,lr} + PROLOG_END + + /* Load pointer to stack structure into R0 */ + mov r0, sp + + /* Call the C worker function */ + adr lr, Return + b __rt_udiv64_worker + +Return + /* Move result data into the appropriate registers and return */ + ldmia sp!,{r0,r1,r2,r3,pc} + ENTRY_END __rt_udiv64 END /* EOF */ diff --git a/reactos/lib/sdk/crt/math/arm/__rt_udiv64_worker.c b/reactos/lib/sdk/crt/math/arm/__rt_udiv64_worker.c new file mode 100644 index 00000000000..36df53cb7e3 --- /dev/null +++ b/reactos/lib/sdk/crt/math/arm/__rt_udiv64_worker.c @@ -0,0 +1,16 @@ +/* + * COPYRIGHT: BSD, see COPYING.ARM in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/math/arm/__rt_udiv64_worker.c + * PURPOSE: Implementation of __rt_udiv64_worker + * PROGRAMMER: Timo Kreuzer + * REFERENCE: http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_div10.s.htm + * http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_udiv.c.htm + */ + +#define __rt_div_worker __rt_udiv64_worker +#define _USE_64_BITS_ + +#include "__rt_div_worker.h" + +/* __rt_udiv64 is implemented in __rt_udiv64.s */