From 0e17cbc7b8cd7c25ab56f7bd19c9934360906b25 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 12 Apr 2015 18:07:19 +0000 Subject: [PATCH] [CRT] Implement __rt_sdiv as a wrapper around the unsigned divide (now factored out into an inline worker function) svn path=/trunk/; revision=67179 --- reactos/lib/sdk/crt/crt.cmake | 3 +- reactos/lib/sdk/crt/libcntpr.cmake | 3 +- reactos/lib/sdk/crt/math/arm/__rt_div.c | 126 +++++++++++++++++++++++ reactos/lib/sdk/crt/math/arm/__rt_sdiv.s | 20 ---- reactos/lib/sdk/crt/math/arm/__rt_udiv.c | 73 ------------- 5 files changed, 128 insertions(+), 97 deletions(-) create mode 100644 reactos/lib/sdk/crt/math/arm/__rt_div.c delete mode 100644 reactos/lib/sdk/crt/math/arm/__rt_sdiv.s delete mode 100644 reactos/lib/sdk/crt/math/arm/__rt_udiv.c diff --git a/reactos/lib/sdk/crt/crt.cmake b/reactos/lib/sdk/crt/crt.cmake index 2bf0752df84..3be45a5411a 100644 --- a/reactos/lib/sdk/crt/crt.cmake +++ b/reactos/lib/sdk/crt/crt.cmake @@ -476,7 +476,7 @@ elseif(ARCH STREQUAL "amd64") endif() elseif(ARCH STREQUAL "arm") list(APPEND LIBCNTPR_SOURCE - math/arm/__rt_udiv.c + math/arm/__rt_div.c ) list(APPEND CRT_ASM_SOURCE math/arm/floor.s @@ -484,7 +484,6 @@ elseif(ARCH STREQUAL "arm") math/arm/pow.s math/arm/__dtou64.s math/arm/__u64tod.s - math/arm/__rt_sdiv.s math/arm/__rt_sdiv64.s math/arm/__rt_udiv64.s ) diff --git a/reactos/lib/sdk/crt/libcntpr.cmake b/reactos/lib/sdk/crt/libcntpr.cmake index 6747dc412a3..95df115ea9e 100644 --- a/reactos/lib/sdk/crt/libcntpr.cmake +++ b/reactos/lib/sdk/crt/libcntpr.cmake @@ -135,7 +135,7 @@ elseif(ARCH STREQUAL "amd64") math/sin.c) elseif(ARCH STREQUAL "arm") list(APPEND LIBCNTPR_SOURCE - math/arm/__rt_udiv.c + math/arm/__rt_div.c ) list(APPEND LIBCNTPR_ASM_SOURCE math/arm/floor.s @@ -143,7 +143,6 @@ elseif(ARCH STREQUAL "arm") math/arm/pow.s math/arm/__dtou64.s math/arm/__u64tod.s - math/arm/__rt_sdiv.s math/arm/__rt_sdiv64.s math/arm/__rt_udiv64.s ) diff --git a/reactos/lib/sdk/crt/math/arm/__rt_div.c b/reactos/lib/sdk/crt/math/arm/__rt_div.c new file mode 100644 index 00000000000..33b86182e2c --- /dev/null +++ b/reactos/lib/sdk/crt/math/arm/__rt_div.c @@ -0,0 +1,126 @@ +/* + * 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 + */ + +typedef struct _ARM_UDIVRESULT +{ + unsigned int quotient; /* to be returned in R0 */ + unsigned int modulus; /* to be returned in R1 */ +} ARM_UDIVRESULT; + +__forceinline +void +__brkdiv0(void) +{ + __emit(0xDEF9); +} + +__forceinline +void +__rt_udiv_internal( + ARM_UDIVRESULT *result, + unsigned int divisor, + unsigned int dividend) +{ + unsigned int shift; + unsigned int mask; + unsigned int quotient; + + if (divisor == 0) + { + /* Raise divide by zero error */ + __brkdiv0(); + } + + 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 = 1 << shift; + + quotient = 0; + do + { + if (dividend >= divisor) + { + quotient |= mask; + dividend -= divisor; + } + divisor >>= 1; + mask >>= 1; + } + while (mask); + + result->quotient = quotient; + result->modulus = dividend; + return; +} + +ARM_UDIVRESULT +__rt_udiv( + unsigned int divisor, + unsigned int dividend) +{ + ARM_UDIVRESULT result; + + __rt_udiv_internal(&result, divisor, dividend); + return result; +} + +typedef struct _ARM_SDIVRESULT +{ + int quotient; /* to be returned in R0 */ + int modulus; /* to be returned in R1 */ +} ARM_SDIVRESULT; + +ARM_SDIVRESULT +__rt_sdiv( + int divisor, + int dividend) +{ + ARM_SDIVRESULT result; + int divisor_sign, dividend_sign; + + dividend_sign = divisor & 0x80000000; + if (dividend_sign) + { + dividend = -dividend; + } + + divisor_sign = divisor & 0x80000000; + if (divisor_sign) + { + divisor = -divisor; + } + + __rt_udiv_internal((ARM_UDIVRESULT*)&result, divisor, dividend); + + if (dividend_sign ^ divisor_sign) + { + result.quotient = -result.quotient; + } + + if (dividend_sign) + { + result.modulus = -result.modulus; + } + + return result; +} diff --git a/reactos/lib/sdk/crt/math/arm/__rt_sdiv.s b/reactos/lib/sdk/crt/math/arm/__rt_sdiv.s deleted file mode 100644 index e7adc38209f..00000000000 --- a/reactos/lib/sdk/crt/math/arm/__rt_sdiv.s +++ /dev/null @@ -1,20 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Implementation of __rt_sdiv - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* CODE **********************************************************************/ - TEXTAREA - - LEAF_ENTRY __rt_sdiv - - LEAF_END __rt_sdiv - - END -/* EOF */ diff --git a/reactos/lib/sdk/crt/math/arm/__rt_udiv.c b/reactos/lib/sdk/crt/math/arm/__rt_udiv.c deleted file mode 100644 index 3cb1ddf3740..00000000000 --- a/reactos/lib/sdk/crt/math/arm/__rt_udiv.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 - */ - -typedef struct _ARM_UDIVRESULT -{ - unsigned int quotient; /* to be returned in R0 */ - unsigned int modulus; /* to be returned in R1 */ -} ARM_UDIVRESULT; - -__forceinline -void -__brkdiv0(void) -{ - __emit(0xDEF9); -} - -ARM_UDIVRESULT -__rt_udiv( - unsigned int divisor, - unsigned int dividend) -{ - ARM_UDIVRESULT result; - unsigned int BitShift; - unsigned int BitMask; - unsigned int Quotient; - - if (divisor == 0) - { - /* Raise divide by zero error */ - __brkdiv0(); - } - - if (divisor > dividend) - { - result.quotient = 0; - result.modulus = divisor; - return result; - } - - /* Get the difference in count of leading zeros between dividend and divisor */ - BitShift = _CountLeadingZeros(divisor); - BitShift -= _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 <<= BitShift; - - BitMask = 1 << BitShift; - - do - { - if (dividend >= divisor) - { - Quotient |= BitMask; - dividend -= divisor; - } - divisor >>= 1; - BitMask >>= 1; - } - while (BitMask); - - result.quotient = Quotient; - result.modulus = dividend; - return result; -} -