diff --git a/src/coreclr/classlibnative/float/CMakeLists.txt b/src/coreclr/classlibnative/float/CMakeLists.txt index 1dbe160248f26e..c6153d5d34c096 100644 --- a/src/coreclr/classlibnative/float/CMakeLists.txt +++ b/src/coreclr/classlibnative/float/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories("../inc") set(FLOAT_SOURCES floatdouble.cpp floatsingle.cpp + divmodint.cpp ) add_library_clr(comfloat_wks OBJECT ${FLOAT_SOURCES}) diff --git a/src/coreclr/classlibnative/float/divmodint.cpp b/src/coreclr/classlibnative/float/divmodint.cpp new file mode 100644 index 00000000000000..d7b194c5587dc7 --- /dev/null +++ b/src/coreclr/classlibnative/float/divmodint.cpp @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifdef TARGET_32BIT + +#include + +#include "divmodint.h" + +#include + +FCIMPL2(int32_t, DivModInt::DivInt32, int32_t dividend, int32_t divisor) + FCALL_CONTRACT; + + return dividend / divisor; +FCIMPLEND + +FCIMPL2(uint32_t, DivModInt::DivUInt32, uint32_t dividend, uint32_t divisor) + FCALL_CONTRACT; + + return dividend / divisor; +FCIMPLEND + +FCIMPL2_VV(int64_t, DivModInt::DivInt64, int64_t dividend, int64_t divisor) + FCALL_CONTRACT; + + return dividend / divisor; +FCIMPLEND + +FCIMPL2_VV(uint64_t, DivModInt::DivUInt64, uint64_t dividend, uint64_t divisor) + FCALL_CONTRACT; + + return dividend / divisor; +FCIMPLEND + +FCIMPL2(int32_t, DivModInt::ModInt32, int32_t dividend, int32_t divisor) + FCALL_CONTRACT; + + return dividend % divisor; +FCIMPLEND + +FCIMPL2(uint32_t, DivModInt::ModUInt32, uint32_t dividend, uint32_t divisor) + FCALL_CONTRACT; + + return dividend % divisor; +FCIMPLEND + +FCIMPL2_VV(int64_t, DivModInt::ModInt64, int64_t dividend, int64_t divisor) + FCALL_CONTRACT; + + return dividend % divisor; +FCIMPLEND + +FCIMPL2_VV(uint64_t, DivModInt::ModUInt64, uint64_t dividend, uint64_t divisor) + FCALL_CONTRACT; + + return dividend % divisor; +FCIMPLEND + +#endif // TARGET_32BIT diff --git a/src/coreclr/classlibnative/inc/divmodint.h b/src/coreclr/classlibnative/inc/divmodint.h new file mode 100644 index 00000000000000..a6aefdbdb78aed --- /dev/null +++ b/src/coreclr/classlibnative/inc/divmodint.h @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef HAVE_DIVMODINT_H +#define HAVE_DIVMODINT_H + +#include +#include + +class DivModInt { +public: + FCDECL2(static int32_t, DivInt32, int32_t dividend, int32_t divisor); + FCDECL2(static uint32_t, DivUInt32, uint32_t dividend, uint32_t divisor); + FCDECL2_VV(static int64_t, DivInt64, int64_t dividend, int64_t divisor); + FCDECL2_VV(static uint64_t, DivUInt64, uint64_t dividend, uint64_t divisor); + FCDECL2(static int32_t, ModInt32, int32_t dividend, int32_t divisor); + FCDECL2(static uint32_t, ModUInt32, uint32_t dividend, uint32_t divisor); + FCDECL2_VV(static int64_t, ModInt64, int64_t dividend, int64_t divisor); + FCDECL2_VV(static uint64_t, ModUInt64, uint64_t dividend, uint64_t divisor); +}; + +#endif // HAVE_DIVMODINT_H diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 8b97677ea11f91..3a7f8a27b9b916 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -34,35 +34,44 @@ JITHELPER(CORINFO_HELP_UNDEF, NULL, METHOD__NIL) - // Arithmetic - JITHELPER(CORINFO_HELP_DIV, JIT_Div, METHOD__NIL) - JITHELPER(CORINFO_HELP_MOD, JIT_Mod, METHOD__NIL) - JITHELPER(CORINFO_HELP_UDIV, JIT_UDiv, METHOD__NIL) - JITHELPER(CORINFO_HELP_UMOD, JIT_UMod, METHOD__NIL) - // CORINFO_HELP_DBL2INT, CORINFO_HELP_DBL2UINT, and CORINFO_HELP_DBL2LONG get // patched for CPUs that support SSE2 (P4 and above). -#ifndef TARGET_64BIT +#ifdef TARGET_32BIT + // Arithmetic + DYNAMICJITHELPER(CORINFO_HELP_DIV, NULL, METHOD__MATH__DIV_INT32) + DYNAMICJITHELPER(CORINFO_HELP_MOD, NULL, METHOD__MATH__MOD_INT32) + DYNAMICJITHELPER(CORINFO_HELP_UDIV, NULL, METHOD__MATH__DIV_UINT32) + DYNAMICJITHELPER(CORINFO_HELP_UMOD, NULL, METHOD__MATH__MOD_UINT32) + JITHELPER(CORINFO_HELP_LLSH, JIT_LLsh, METHOD__NIL) JITHELPER(CORINFO_HELP_LRSH, JIT_LRsh, METHOD__NIL) JITHELPER(CORINFO_HELP_LRSZ, JIT_LRsz, METHOD__NIL) -#else // !TARGET_64BIT +#else // TARGET_32BIT + DYNAMICJITHELPER(CORINFO_HELP_DIV, NULL, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_MOD, NULL, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_UDIV, NULL, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_UMOD, NULL, METHOD__NIL) + JITHELPER(CORINFO_HELP_LLSH, NULL, METHOD__NIL) JITHELPER(CORINFO_HELP_LRSH, NULL, METHOD__NIL) JITHELPER(CORINFO_HELP_LRSZ, NULL, METHOD__NIL) -#endif // TARGET_64BIT +#endif // TARGET_32BIT JITHELPER(CORINFO_HELP_LMUL, JIT_LMul, METHOD__NIL) -#ifndef TARGET_64BIT +#ifdef TARGET_32BIT DYNAMICJITHELPER(CORINFO_HELP_LMUL_OVF, NULL, METHOD__MATH__MULTIPLY_CHECKED_INT64) DYNAMICJITHELPER(CORINFO_HELP_ULMUL_OVF, NULL, METHOD__MATH__MULTIPLY_CHECKED_UINT64) + DYNAMICJITHELPER(CORINFO_HELP_LDIV, NULL, METHOD__MATH__DIV_INT64) + DYNAMICJITHELPER(CORINFO_HELP_LMOD, NULL, METHOD__MATH__MOD_INT64) + DYNAMICJITHELPER(CORINFO_HELP_ULDIV, NULL, METHOD__MATH__DIV_UINT64) + DYNAMICJITHELPER(CORINFO_HELP_ULMOD, NULL, METHOD__MATH__MOD_UINT64) #else DYNAMICJITHELPER(CORINFO_HELP_LMUL_OVF, NULL, METHOD__NIL) DYNAMICJITHELPER(CORINFO_HELP_ULMUL_OVF, NULL, METHOD__NIL) -#endif // TARGET_64BIT - JITHELPER(CORINFO_HELP_LDIV, JIT_LDiv, METHOD__NIL) - JITHELPER(CORINFO_HELP_LMOD, JIT_LMod, METHOD__NIL) - JITHELPER(CORINFO_HELP_ULDIV, JIT_ULDiv, METHOD__NIL) - JITHELPER(CORINFO_HELP_ULMOD, JIT_ULMod, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_LDIV, NULL, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_LMOD, NULL, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_ULDIV, NULL, METHOD__NIL) + DYNAMICJITHELPER(CORINFO_HELP_ULMOD, NULL, METHOD__NIL) +#endif // TARGET_32BIT JITHELPER(CORINFO_HELP_LNG2DBL, JIT_Lng2Dbl, METHOD__NIL) JITHELPER(CORINFO_HELP_ULNG2DBL, JIT_ULng2Dbl, METHOD__NIL) JITHELPER(CORINFO_HELP_DBL2INT, JIT_Dbl2Int, METHOD__NIL) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index b06f2f3d5eb30c..6a9c7535178c3f 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -18,5 +18,7 @@ public static int OffsetToStringData [Intrinsic] public static extern void InitializeArray(Array array, RuntimeFieldHandle fldHandle); + + public const string QCall = "*"; } } diff --git a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp index 6e3f4d73de8af2..edefb29ccbd785 100644 --- a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp @@ -56,25 +56,25 @@ FCIMPL1_D(uint32_t, RhpDbl2UInt, double val) FCIMPLEND #ifndef HOST_64BIT -EXTERN_C int64_t QCALLTYPE RhpLDiv(int64_t i, int64_t j) +EXTERN_C int64_t QCALLTYPE DivInt64Internal(int64_t i, int64_t j) { ASSERT(j && "Divide by zero!"); return i / j; } -EXTERN_C uint64_t QCALLTYPE RhpULDiv(uint64_t i, uint64_t j) +EXTERN_C uint64_t QCALLTYPE DivUInt64Internal(uint64_t i, uint64_t j) { ASSERT(j && "Divide by zero!"); return i / j; } -EXTERN_C int64_t QCALLTYPE RhpLMod(int64_t i, int64_t j) +EXTERN_C int64_t QCALLTYPE ModInt64Internal(int64_t i, int64_t j) { ASSERT(j && "Divide by zero!"); return i % j; } -EXTERN_C uint64_t QCALLTYPE RhpULMod(uint64_t i, uint64_t j) +EXTERN_C uint64_t QCALLTYPE ModUInt64Internal(uint64_t i, uint64_t j) { ASSERT(j && "Divide by zero!"); return i % j; @@ -95,25 +95,25 @@ FCIMPLEND #endif #ifdef HOST_ARM -EXTERN_C int32_t F_CALL_CONV RhpIDiv(int32_t i, int32_t j) +EXTERN_C int32_t F_CALL_CONV DivInt32Internal(int32_t i, int32_t j) { ASSERT(j && "Divide by zero!"); return i / j; } -EXTERN_C uint32_t F_CALL_CONV RhpUDiv(uint32_t i, uint32_t j) +EXTERN_C uint32_t F_CALL_CONV DivUInt32Internal(uint32_t i, uint32_t j) { ASSERT(j && "Divide by zero!"); return i / j; } -EXTERN_C int32_t F_CALL_CONV RhpIMod(int32_t i, int32_t j) +EXTERN_C int32_t F_CALL_CONV ModInt32Internal(int32_t i, int32_t j) { ASSERT(j && "Divide by zero!"); return i % j; } -EXTERN_C uint32_t F_CALL_CONV RhpUMod(uint32_t i, uint32_t j) +EXTERN_C uint32_t F_CALL_CONV ModUInt32Internal(uint32_t i, uint32_t j) { ASSERT(j && "Divide by zero!"); return i % j; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs deleted file mode 100644 index df8c6d407901ff..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics; -using System.Runtime; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Internal.Runtime.CompilerHelpers -{ - /// - /// Math helpers for generated code. The helpers here are referenced by the runtime. - /// - [StackTraceHidden] - internal static partial class MathHelpers - { -#if !TARGET_64BIT - private const string RuntimeLibrary = "*"; - - [LibraryImport(RuntimeLibrary)] - [SuppressGCTransition] - private static partial ulong RhpULMod(ulong dividend, ulong divisor); - - public static ulong ULMod(ulong dividend, ulong divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - - return RhpULMod(dividend, divisor); - } - - [LibraryImport(RuntimeLibrary)] - [SuppressGCTransition] - private static partial long RhpLMod(long dividend, long divisor); - - public static long LMod(long dividend, long divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - if (divisor == -1 && dividend == long.MinValue) - ThrowHelper.ThrowOverflowException(); - - return RhpLMod(dividend, divisor); - } - - [LibraryImport(RuntimeLibrary)] - [SuppressGCTransition] - private static partial ulong RhpULDiv(ulong dividend, ulong divisor); - - public static ulong ULDiv(ulong dividend, ulong divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - - return RhpULDiv(dividend, divisor); - } - - [LibraryImport(RuntimeLibrary)] - [SuppressGCTransition] - private static partial long RhpLDiv(long dividend, long divisor); - - public static long LDiv(long dividend, long divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - if (divisor == -1 && dividend == long.MinValue) - ThrowHelper.ThrowOverflowException(); - - return RhpLDiv(dividend, divisor); - } - -#if TARGET_ARM - [RuntimeImport(RuntimeLibrary, "RhpIDiv")] - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int RhpIDiv(int dividend, int divisor); - - public static int IDiv(int dividend, int divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - if (divisor == -1 && dividend == int.MinValue) - ThrowHelper.ThrowOverflowException(); - - return RhpIDiv(dividend, divisor); - } - - [RuntimeImport(RuntimeLibrary, "RhpUDiv")] - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern uint RhpUDiv(uint dividend, uint divisor); - - public static long UDiv(uint dividend, uint divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - - return RhpUDiv(dividend, divisor); - } - - [RuntimeImport(RuntimeLibrary, "RhpIMod")] - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int RhpIMod(int dividend, int divisor); - - public static int IMod(int dividend, int divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - if (divisor == -1 && dividend == int.MinValue) - ThrowHelper.ThrowOverflowException(); - - return RhpIMod(dividend, divisor); - } - - [RuntimeImport(RuntimeLibrary, "RhpUMod")] - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern uint RhpUMod(uint dividend, uint divisor); - - public static long UMod(uint dividend, uint divisor) - { - if (divisor == 0) - ThrowHelper.ThrowDivideByZeroException(); - - return RhpUMod(dividend, divisor); - } -#endif // TARGET_ARM -#endif // TARGET_64BIT - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index a37ba28ad85f15..90f5a4fdfa91aa 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -116,7 +116,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index 1d78df875c125b..c510a38a0a9c65 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -233,30 +233,30 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, } break; - case ReadyToRunHelper.Mod: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "IMod"); + case ReadyToRunHelper.Div: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("DivInt32", null); break; - case ReadyToRunHelper.UMod: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "UMod"); + case ReadyToRunHelper.UDiv: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("DivUInt32", null); break; - case ReadyToRunHelper.ULMod: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "ULMod"); + case ReadyToRunHelper.LDiv: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("DivInt64", null); break; - case ReadyToRunHelper.LMod: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "LMod"); + case ReadyToRunHelper.ULDiv: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("DivUInt64", null); break; - case ReadyToRunHelper.Div: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "IDiv"); + case ReadyToRunHelper.Mod: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ModInt32", null); break; - case ReadyToRunHelper.UDiv: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "UDiv"); + case ReadyToRunHelper.UMod: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ModUInt32", null); break; - case ReadyToRunHelper.ULDiv: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "ULDiv"); + case ReadyToRunHelper.LMod: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ModInt64", null); break; - case ReadyToRunHelper.LDiv: - methodDesc = context.GetHelperEntryPoint("MathHelpers", "LDiv"); + case ReadyToRunHelper.ULMod: + methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("ModUInt64", null); break; case ReadyToRunHelper.LRsz: diff --git a/src/coreclr/vm/corelib.cpp b/src/coreclr/vm/corelib.cpp index beb66a2086a226..c271a057d12d68 100644 --- a/src/coreclr/vm/corelib.cpp +++ b/src/coreclr/vm/corelib.cpp @@ -28,6 +28,7 @@ #include "comsynchronizable.h" #include "floatdouble.h" #include "floatsingle.h" +#include "divmodint.h" #include "comdatetime.h" #include "debugdebugger.h" #include "assemblynative.hpp" diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 7a5fe8d99743b2..ea9d3d9d12b410 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -264,14 +264,23 @@ DEFINE_CLASS(INT128, System, Int128) DEFINE_CLASS(UINT128, System, UInt128) DEFINE_CLASS(MATH, System, Math) -#ifndef TARGET_64BIT -DEFINE_METHOD(MATH, MULTIPLY_CHECKED_INT64, MultiplyChecked, SM_Long_Long_RetLong) -DEFINE_METHOD(MATH, MULTIPLY_CHECKED_UINT64, MultiplyChecked, SM_ULong_ULong_RetULong) -#endif -DEFINE_METHOD(MATH, CONVERT_TO_INT32_CHECKED, ConvertToInt32Checked, NoSig) -DEFINE_METHOD(MATH, CONVERT_TO_UINT32_CHECKED, ConvertToUInt32Checked, NoSig) -DEFINE_METHOD(MATH, CONVERT_TO_INT64_CHECKED, ConvertToInt64Checked, NoSig) -DEFINE_METHOD(MATH, CONVERT_TO_UINT64_CHECKED, ConvertToUInt64Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_INT32_CHECKED, ConvertToInt32Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_UINT32_CHECKED, ConvertToUInt32Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_INT64_CHECKED, ConvertToInt64Checked, NoSig) +DEFINE_METHOD(MATH, CONVERT_TO_UINT64_CHECKED, ConvertToUInt64Checked, NoSig) + +#ifdef TARGET_32BIT +DEFINE_METHOD(MATH, MULTIPLY_CHECKED_INT64, MultiplyChecked, SM_Long_Long_RetLong) +DEFINE_METHOD(MATH, MULTIPLY_CHECKED_UINT64, MultiplyChecked, SM_ULong_ULong_RetULong) +DEFINE_METHOD(MATH, DIV_INT32, DivInt32, NoSig) +DEFINE_METHOD(MATH, DIV_UINT32, DivUInt32, NoSig) +DEFINE_METHOD(MATH, DIV_INT64, DivInt64, NoSig) +DEFINE_METHOD(MATH, DIV_UINT64, DivUInt64, NoSig) +DEFINE_METHOD(MATH, MOD_INT32, ModInt32, NoSig) +DEFINE_METHOD(MATH, MOD_UINT32, ModUInt32, NoSig) +DEFINE_METHOD(MATH, MOD_INT64, ModInt64, NoSig) +DEFINE_METHOD(MATH, MOD_UINT64, ModUInt64, NoSig) +#endif // TARGET_32BIT DEFINE_CLASS(DYNAMICMETHOD, ReflectionEmit, DynamicMethod) diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 7535c717c3955b..951dfd3b5e3eeb 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -213,6 +213,16 @@ FCFuncStart(gMathFuncs) FCFuncElement("Sqrt", COMDouble::Sqrt) FCFuncElement("Tan", COMDouble::Tan) FCFuncElement("Tanh", COMDouble::Tanh) +#ifdef TARGET_32BIT + FCFuncElement("DivInt32Internal", DivModInt::DivInt32) + FCFuncElement("DivUInt32Internal", DivModInt::DivUInt32) + FCFuncElement("DivInt64Internal", DivModInt::DivInt64) + FCFuncElement("DivUInt64Internal", DivModInt::DivUInt64) + FCFuncElement("ModInt32Internal", DivModInt::ModInt32) + FCFuncElement("ModUInt32Internal", DivModInt::ModUInt32) + FCFuncElement("ModInt64Internal", DivModInt::ModInt64) + FCFuncElement("ModUInt64Internal", DivModInt::ModUInt64) +#endif // TARGET_32BIT FCFuncEnd() FCFuncStart(gMathFFuncs) diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index e116ff3b26994f..478ec0d044759c 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -127,208 +127,6 @@ HCIMPL2_VV(INT64, JIT_LMul, INT64 val1, INT64 val2) HCIMPLEND #endif // !TARGET_X86 || TARGET_UNIX -/*********************************************************************/ -HCIMPL2(INT32, JIT_Div, INT32 dividend, INT32 divisor) -{ - FCALL_CONTRACT; - - RuntimeExceptionKind ehKind; - - if (((UINT32) (divisor + 1)) <= 1) // Unsigned test for divisor in [-1 .. 0] - { - if (divisor == 0) - { - ehKind = kDivideByZeroException; - goto ThrowExcep; - } - else if (divisor == -1) - { - if (dividend == INT32_MIN) - { - ehKind = kOverflowException; - goto ThrowExcep; - } - return -dividend; - } - } - - return(dividend / divisor); - -ThrowExcep: - FCThrow(ehKind); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2(INT32, JIT_Mod, INT32 dividend, INT32 divisor) -{ - FCALL_CONTRACT; - - RuntimeExceptionKind ehKind; - - if (((UINT32) (divisor + 1)) <= 1) // Unsigned test for divisor in [-1 .. 0] - { - if (divisor == 0) - { - ehKind = kDivideByZeroException; - goto ThrowExcep; - } - else if (divisor == -1) - { - if (dividend == INT32_MIN) - { - ehKind = kOverflowException; - goto ThrowExcep; - } - return 0; - } - } - - return(dividend % divisor); - -ThrowExcep: - FCThrow(ehKind); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2(UINT32, JIT_UDiv, UINT32 dividend, UINT32 divisor) -{ - FCALL_CONTRACT; - - if (divisor == 0) - FCThrow(kDivideByZeroException); - - return(dividend / divisor); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2(UINT32, JIT_UMod, UINT32 dividend, UINT32 divisor) -{ - FCALL_CONTRACT; - - if (divisor == 0) - FCThrow(kDivideByZeroException); - - return(dividend % divisor); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2_VV(INT64, JIT_LDiv, INT64 dividend, INT64 divisor) -{ - FCALL_CONTRACT; - - RuntimeExceptionKind ehKind; - - if (Is32BitSigned(divisor)) - { - if ((INT32)divisor == 0) - { - ehKind = kDivideByZeroException; - goto ThrowExcep; - } - - if ((INT32)divisor == -1) - { - if ((UINT64) dividend == UI64(0x8000000000000000)) - { - ehKind = kOverflowException; - goto ThrowExcep; - } - return -dividend; - } - - // Check for -ive or +ive numbers in the range -2**31 to 2**31 - if (Is32BitSigned(dividend)) - return((INT32)dividend / (INT32)divisor); - } - - // For all other combinations fallback to int64 div. - return(dividend / divisor); - -ThrowExcep: - FCThrow(ehKind); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2_VV(INT64, JIT_LMod, INT64 dividend, INT64 divisor) -{ - FCALL_CONTRACT; - - RuntimeExceptionKind ehKind; - - if (Is32BitSigned(divisor)) - { - if ((INT32)divisor == 0) - { - ehKind = kDivideByZeroException; - goto ThrowExcep; - } - - if ((INT32)divisor == -1) - { - // TODO, we really should remove this as it lengthens the code path - // and the spec really says that it should not throw an exception. - if ((UINT64) dividend == UI64(0x8000000000000000)) - { - ehKind = kOverflowException; - goto ThrowExcep; - } - return 0; - } - - // Check for -ive or +ive numbers in the range -2**31 to 2**31 - if (Is32BitSigned(dividend)) - return((INT32)dividend % (INT32)divisor); - } - - // For all other combinations fallback to int64 div. - return(dividend % divisor); - -ThrowExcep: - FCThrow(ehKind); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2_VV(UINT64, JIT_ULDiv, UINT64 dividend, UINT64 divisor) -{ - FCALL_CONTRACT; - - if (Hi32Bits(divisor) == 0) - { - if ((UINT32)(divisor) == 0) - FCThrow(kDivideByZeroException); - - if (Hi32Bits(dividend) == 0) - return((UINT32)dividend / (UINT32)divisor); - } - - return(dividend / divisor); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL2_VV(UINT64, JIT_ULMod, UINT64 dividend, UINT64 divisor) -{ - FCALL_CONTRACT; - - if (Hi32Bits(divisor) == 0) - { - if ((UINT32)(divisor) == 0) - FCThrow(kDivideByZeroException); - - if (Hi32Bits(dividend) == 0) - return((UINT32)dividend % (UINT32)divisor); - } - - return(dividend % divisor); -} -HCIMPLEND - #if !defined(HOST_64BIT) && !defined(TARGET_X86) /*********************************************************************/ HCIMPL2_VV(UINT64, JIT_LLsh, UINT64 num, int shift) @@ -4049,7 +3847,7 @@ bool IndirectionAllowedForJitHelper(CorInfoHelpFunc ftnNum) { return false; } - + return true; } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 51e003bae50afc..0842c6756752f1 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -570,6 +570,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.DivModInt.cs b/src/libraries/System.Private.CoreLib/src/System/Math.DivModInt.cs new file mode 100644 index 00000000000000..ef6c219482f8de --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Math.DivModInt.cs @@ -0,0 +1,224 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; + +#if NATIVEAOT +using System.Runtime.InteropServices; +#endif + +namespace System +{ + /// + /// Math helpers for generated code. The helpers here are referenced by the runtime. + /// + public static partial class Math + { + [StackTraceHidden] + internal static int DivInt32(int dividend, int divisor) + { + if ((uint)(divisor + 1) <= 1) // Unsigned test for divisor in [-1 .. 0] + { + if (divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + else if (divisor == -1) + { + if (dividend == int.MinValue) + { + ThrowHelper.ThrowOverflowException(); + } + return -dividend; + } + } + + return DivInt32Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static uint DivUInt32(uint dividend, uint divisor) + { + if (divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + + return DivUInt32Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static long DivInt64(long dividend, long divisor) + { + if ((int)((ulong)divisor >> 32) == (int)(((ulong)(int)divisor) >> 32)) + { + if ((int)divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + + if ((int)divisor == -1) + { + if (dividend == long.MinValue) + { + ThrowHelper.ThrowOverflowException(); + } + return -dividend; + } + + // Check for -ive or +ive numbers in the range -2**31 to 2**31 + if ((int)((ulong)dividend >> 32) == (int)(((ulong)(int)dividend) >> 32)) + { + return DivInt32Internal((int)dividend, (int)divisor); + } + } + + return DivInt64Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static ulong DivUInt64(ulong dividend, ulong divisor) + { + if ((int)(divisor >> 32) == 0) + { + if ((uint)divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + + if ((int)(dividend >> 32) == 0) + { + return DivUInt32Internal((uint)dividend, (uint)divisor); + } + } + + return DivUInt64Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static int ModInt32(int dividend, int divisor) + { + if ((uint)(divisor + 1) <= 1) // Unsigned test for divisor in [-1 .. 0] + { + if (divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + else if (divisor == -1) + { + if (dividend == int.MinValue) + { + ThrowHelper.ThrowOverflowException(); + } + return 0; + } + } + + return ModInt32Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static uint ModUInt32(uint dividend, uint divisor) + { + if (divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + + return ModUInt32Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static long ModInt64(long dividend, long divisor) + { + if ((int)((ulong)divisor >> 32) == (int)(((ulong)(int)divisor) >> 32)) + { + if ((int)divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + + if ((int)divisor == -1) + { + if (dividend == long.MinValue) + { + ThrowHelper.ThrowOverflowException(); + } + return 0; + } + + if ((int)((ulong)dividend >> 32) == (int)(((ulong)(int)dividend) >> 32)) + { + return ModInt32Internal((int)dividend, (int)divisor); + } + } + + return ModInt64Internal(dividend, divisor); + } + + [StackTraceHidden] + internal static ulong ModUInt64(ulong dividend, ulong divisor) + { + if ((int)(divisor >> 32) == 0) + { + if ((uint)divisor == 0) + { + ThrowHelper.ThrowDivideByZeroException(); + } + + if ((int)(dividend >> 32) == 0) + { + return ModUInt32Internal((uint)dividend, (uint)divisor); + } + } + + return ModUInt64Internal(dividend, divisor); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern int DivInt32Internal(int dividend, int divisor); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern uint DivUInt32Internal(uint dividend, uint divisor); + +#if NATIVEAOT + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DivInt64Internal"), SuppressGCTransition] + private static partial long DivInt64Internal(long dividend, long divisor); +#else + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern long DivInt64Internal(long dividend, long divisor); +#endif + +#if NATIVEAOT + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DivUInt64Internal"), SuppressGCTransition] + private static partial ulong DivUInt64Internal(ulong dividend, ulong divisor); +#else + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern ulong DivUInt64Internal(ulong dividend, ulong divisor); +#endif + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern int ModInt32Internal(int dividend, int divisor); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern uint ModUInt32Internal(uint dividend, uint divisor); + +#if NATIVEAOT + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ModInt64Internal"), SuppressGCTransition] + private static partial long ModInt64Internal(long dividend, long divisor); +#else + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern long ModInt64Internal(long dividend, long divisor); +#endif + +#if NATIVEAOT + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ModUInt64Internal"), SuppressGCTransition] + private static partial ulong ModUInt64Internal(ulong dividend, ulong divisor); +#else + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern ulong ModUInt64Internal(ulong dividend, ulong divisor); +#endif + } +}