diff --git a/.vsconfig b/.vsconfig index 402799aa5537e..f949b82c3744d 100644 --- a/.vsconfig +++ b/.vsconfig @@ -41,7 +41,6 @@ "Microsoft.VisualStudio.Component.VC.CMake.Project", "Microsoft.VisualStudio.Component.VC.CoreIde", "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", - "Microsoft.VisualStudio.Component.VC.Tools.ARM", "Microsoft.VisualStudio.Component.VC.Tools.ARM64", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "Microsoft.VisualStudio.Component.Windows10SDK.19041", diff --git a/docs/infra/test-configurations.md b/docs/infra/test-configurations.md index 3b96e74e66c82..eabcc14bd8c1e 100644 --- a/docs/infra/test-configurations.md +++ b/docs/infra/test-configurations.md @@ -29,7 +29,6 @@ All builds are - Windows 10 x64 Client VS2019 - x64 Release - x86 Release - - arm32 Release - arm64 Release - Ubuntu 18.04 x64 - Linux x64 Release diff --git a/docs/workflow/README.md b/docs/workflow/README.md index dbef0e3e7a533..74bbc892f3efa 100644 --- a/docs/workflow/README.md +++ b/docs/workflow/README.md @@ -17,8 +17,8 @@ The repo can be built for the following platforms, using the provided setup and | :---- | :------: | :------: | :------: | :------: | | x64 | ✔ | ✔ | ✔ | ✔ | | x86 | ✔ | | | | -| ARM | ✔ | ✔ | | | -| ARM64 | ✔ | ✔ | ✔ | | +| Arm32 | | ✔ | | | +| Arm64 | ✔ | ✔ | ✔ | | | | [Requirements](requirements/windows-requirements.md) | [Requirements](requirements/linux-requirements.md) | [Requirements](requirements/macos-requirements.md) | [Requirements](requirements/freebsd-requirements.md) Additionally, keep in mind that cloning the full history of this repo takes roughly 400-500 MB of network transfer, inflating to a repository that can consume somewhere between 1 to 1.5 GB. A build of the repo can take somewhere between 10 and 20 GB of space for a single OS and Platform configuration depending on the portions of the product built. This might increase over time, so consider this to be a minimum bar for working with this codebase. diff --git a/docs/workflow/building/coreclr/cross-building.md b/docs/workflow/building/coreclr/cross-building.md index 4fbbdebdd404e..7bbe28abb6410 100644 --- a/docs/workflow/building/coreclr/cross-building.md +++ b/docs/workflow/building/coreclr/cross-building.md @@ -1,7 +1,7 @@ # Cross-Building for Different Architectures and Operating Systems * [Windows Cross-Building](#windows-cross-building) - * [Cross-Compiling for ARM32 and ARM64 on Windows](#cross-compiling-for-arm32-and-arm64-on-windows) + * [Cross-Compiling for ARM64 on Windows](#cross-compiling-for-arm64-on-windows) * [Cross-Compiling for x86 on Windows](#cross-compiling-for-x86-on-windows) * [macOS Cross-Building](#macos-cross-building) * [Linux Cross-Building](#linux-cross-building) @@ -21,9 +21,9 @@ This guide will go more in-depth on how to do cross-building across multiple ope This section will go over cross-compiling on Windows. Currently, Windows allows you to cross-compile from x64 to basically any other architecture. -### Cross-Compiling for ARM32 and ARM64 on Windows +### Cross-Compiling for ARM64 on Windows -To do cross-compilation for ARM32/ARM64 on Windows, first make sure you have the appropriate tools and Windows SDK installed. This is described in detail in the [Windows requirements doc](/docs/workflow/requirements/windows-requirements.md#visual-studio). +To do cross-compilation for ARM64 on Windows, first make sure you have the appropriate tools and Windows SDK installed. This is described in detail in the [Windows requirements doc](/docs/workflow/requirements/windows-requirements.md#visual-studio). Once you have all the required dependencies, it is a straightforward process. Windows knows how to cross-build behind curtains, so all you have to do is specify which architecture you want to build for: diff --git a/docs/workflow/requirements/windows-requirements.md b/docs/workflow/requirements/windows-requirements.md index 4ee557ce63c35..06675bdb8c39e 100644 --- a/docs/workflow/requirements/windows-requirements.md +++ b/docs/workflow/requirements/windows-requirements.md @@ -35,8 +35,7 @@ Install [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/). The * It's recommended to use **Workloads** installation approach. The following are the minimum requirements: * **.NET Desktop Development** with all default components, * **Desktop Development with C++** with all default components. -* To build for Arm32 or Arm64, make sure that you have the right architecture-specific compilers installed. In the **Individual components** window, in the **Compilers, build tools, and runtimes** section: - * For Arm32, check the box for _MSVC v143* VS 2022 C++ ARM build tools (Latest)_. +* To build for Arm64, make sure that you have the right architecture-specific compilers installed. In the **Individual components** window, in the **Compilers, build tools, and runtimes** section: * For Arm64, check the box for _MSVC v143* VS 2022 C++ ARM64 build tools (Latest)_. * To build the tests, you will need some additional components: * **C++/CLI support for v142 build tools (Latest)**. diff --git a/eng/Subsets.props b/eng/Subsets.props index f1af6a47bfddc..093120feb2411 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -267,19 +267,6 @@ Category="clr" /> - - - - diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml index 55060a01171c6..fb53430c03791 100644 --- a/eng/pipelines/mono/templates/workloads-build.yml +++ b/eng/pipelines/mono/templates/workloads-build.yml @@ -72,7 +72,6 @@ jobs: IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Wasi*.nupkg IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Templates*.nupkg - IntermediateArtifacts/windows_arm/Shipping/Microsoft.NETCore.App.Runtime.win-arm*.nupkg IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.win-arm64*.nupkg IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.win-x64*.nupkg IntermediateArtifacts/windows_x86/Shipping/Microsoft.NETCore.App.Runtime.win-x86*.nupkg diff --git a/src/coreclr/CMakeSettings.json b/src/coreclr/CMakeSettings.json index c60469ea8ad48..10c8ff47cb5bf 100644 --- a/src/coreclr/CMakeSettings.json +++ b/src/coreclr/CMakeSettings.json @@ -50,29 +50,6 @@ "ctestCommandArgs": "", "inheritEnvironments": [ "msvc_x86" ] }, - { - "name": "windows.arm.Debug", - "generator": "Ninja", - "configurationType": "Debug", - "buildRoot": "${env.artifactsObj}\\${name}", - "installRoot": "${env.artifactsBin}\\${name}", - "cmakeCommandArgs": "-DCLR_CMAKE_HOST_ARCH=arm", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_arm" ] - }, - { - "name": "windows.arm.Release", - "generator": "Ninja", - "configurationType": "Release", - "buildRoot": "${env.artifactsObj}\\${name}", - "installRoot": "${env.artifactsBin}\\${name}", - "cmakeCommandArgs": "-DCLR_CMAKE_HOST_ARCH=arm", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_arm" ], - "variables": [] - }, { "name": "windows.arm64.Debug", "generator": "Ninja", @@ -98,4 +75,4 @@ "variables": [] } ] -} \ No newline at end of file +} diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index a8fca255b8611..40ced7a1f977c 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -42,7 +42,6 @@ set __BuildAll= set __TargetArchX64=0 set __TargetArchX86=0 -set __TargetArchArm=0 set __TargetArchArm64=0 set __BuildTypeDebug=0 @@ -87,7 +86,6 @@ if /i "%1" == "--help" goto Usage if /i "%1" == "-all" (set __BuildAll=1&shift&goto Arg_Loop) if /i "%1" == "-x64" (set __TargetArchX64=1&shift&goto Arg_Loop) if /i "%1" == "-x86" (set __TargetArchX86=1&shift&goto Arg_Loop) -if /i "%1" == "-arm" (set __TargetArchArm=1&shift&goto Arg_Loop) if /i "%1" == "-arm64" (set __TargetArchArm64=1&shift&goto Arg_Loop) if /i "%1" == "-debug" (set __BuildTypeDebug=1&shift&goto Arg_Loop) @@ -101,7 +99,6 @@ REM don't add more, use the - syntax instead if /i "%1" == "all" (set __BuildAll=1&shift&goto Arg_Loop) if /i "%1" == "x64" (set __TargetArchX64=1&shift&goto Arg_Loop) if /i "%1" == "x86" (set __TargetArchX86=1&shift&goto Arg_Loop) -if /i "%1" == "arm" (set __TargetArchArm=1&shift&goto Arg_Loop) if /i "%1" == "arm64" (set __TargetArchArm64=1&shift&goto Arg_Loop) if /i "%1" == "debug" (set __BuildTypeDebug=1&shift&goto Arg_Loop) @@ -165,7 +162,7 @@ if defined VCINSTALLDIR ( if defined __BuildAll goto BuildAll -set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm + __TargetArchArm64 +set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm64 if %__TotalSpecifiedTargetArch% GTR 1 ( echo Error: more than one build architecture specified, but "all" not specified. goto Usage @@ -176,7 +173,6 @@ if "%__ProcessorArch%"=="" set __ProcessorArch=%PROCESSOR_ARCHITECTURE% if %__TargetArchX64%==1 set __TargetArch=x64 if %__TargetArchX86%==1 set __TargetArch=x86 -if %__TargetArchArm%==1 set __TargetArch=arm if %__TargetArchArm64%==1 set __TargetArch=arm64 if "%__HostArch%" == "" set __HostArch=%__TargetArch% @@ -191,10 +187,6 @@ if %__BuildTypeChecked%==1 set __BuildType=Checked if %__BuildTypeRelease%==1 set __BuildType=Release if %__EnforcePgo%==1 ( - if %__TargetArchArm%==1 ( - echo NOTICE: enforcepgo does nothing on arm architecture - set __EnforcePgo=0 - ) if %__TargetArchArm64%==1 ( echo NOTICE: enforcepgo does nothing on arm64 architecture set __EnforcePgo=0 @@ -451,7 +443,7 @@ REM ============================================================================ set __TargetArchList= -set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm + __TargetArchArm64 +set /A __TotalSpecifiedTargetArch=__TargetArchX64 + __TargetArchX86 + __TargetArchArm64 if %__TotalSpecifiedTargetArch% EQU 0 ( REM Nothing specified means we want to build all architectures. set __TargetArchList=x64 x86 arm arm64 @@ -461,7 +453,6 @@ REM Otherwise, add all the specified architectures to the list. if %__TargetArchX64%==1 set __TargetArchList=%__TargetArchList% x64 if %__TargetArchX86%==1 set __TargetArchList=%__TargetArchList% x86 -if %__TargetArchArm%==1 set __TargetArchList=%__TargetArchList% arm if %__TargetArchArm64%==1 set __TargetArchList=%__TargetArchList% arm64 set __BuildTypeList= @@ -545,7 +536,7 @@ echo All arguments are optional. The options are: echo. echo.-? -h -help --help: view this message. echo -all: Builds all configurations and platforms. -echo Build architecture: one of -x64, -x86, -arm, -arm64 ^(default: -x64^). +echo Build architecture: one of -x64, -x86, -arm64 ^(default: -x64^). echo Build type: one of -Debug, -Checked, -Release ^(default: -Debug^). echo -component ^ : specify this option one or more times to limit components built to those specified. echo Allowed ^: hosts jit alljits runtime paltests iltools nativeaot spmi diff --git a/src/coreclr/debug/di/arm/floatconversion.asm b/src/coreclr/debug/di/arm/floatconversion.asm deleted file mode 100644 index a8b62b8892121..0000000000000 --- a/src/coreclr/debug/di/arm/floatconversion.asm +++ /dev/null @@ -1,17 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" - -;; Arguments -;; input: (in R0) the address of the ULONGLONG to be converted to a double -;; output: the double corresponding to the ULONGLONG input value - - LEAF_ENTRY FPFillR8 - vldr D0, [R0] - bx lr - LEAF_END - - -;; Must be at very end of file - END diff --git a/src/coreclr/debug/ee/arm/dbghelpers.asm b/src/coreclr/debug/ee/arm/dbghelpers.asm deleted file mode 100644 index 0d1040859af44..0000000000000 --- a/src/coreclr/debug/ee/arm/dbghelpers.asm +++ /dev/null @@ -1,89 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" -#include "asmconstants.h" - - IMPORT FuncEvalHijackWorker - IMPORT FuncEvalHijackPersonalityRoutine - IMPORT ExceptionHijackWorker - IMPORT ExceptionHijackPersonalityRoutine - EXPORT ExceptionHijackEnd - - MACRO - CHECK_STACK_ALIGNMENT - -#ifdef _DEBUG - push {r0} - add r0, sp, #4 - tst r0, #7 - pop {r0} - beq %0 - EMIT_BREAKPOINT -0 -#endif - MEND - - TEXTAREA - -; -; hijacking stub used to perform a func-eval, see Debugger::FuncEvalSetup() for use. -; -; on entry: -; r0 : pointer to DebuggerEval object -; - - NESTED_ENTRY FuncEvalHijack,,FuncEvalHijackPersonalityRoutine - - ; NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if - ; you change the prolog you will also need to update the personality routine. - - ; push arg to the stack so our personality routine can find it - ; push lr to get good stacktrace in debugger - PROLOG_PUSH {r0,lr} - - CHECK_STACK_ALIGNMENT - - ; FuncEvalHijackWorker returns the address we should jump to. - bl FuncEvalHijackWorker - - ; effective NOP to terminate unwind - mov r2, r2 - - EPILOG_STACK_FREE 8 - EPILOG_BRANCH_REG r0 - - NESTED_END FuncEvalHijack - -; -; This is the general purpose hijacking stub. DacDbiInterfaceImpl::Hijack() will -; set the registers with the appropriate parameters from out-of-process. -; -; on entry: -; r0 : pointer to CONTEXT -; r1 : pointer to EXCEPTION_RECORD -; r2 : EHijackReason -; r3 : void* pdata -; - - NESTED_ENTRY ExceptionHijack,,ExceptionHijackPersonalityRoutine - - CHECK_STACK_ALIGNMENT - - ; make the call - bl ExceptionHijackWorker - - ; effective NOP to terminate unwind - mov r3, r3 - - ; *** should never get here *** - EMIT_BREAKPOINT - -; exported label so the debugger knows where the end of this function is -ExceptionHijackEnd - NESTED_END - - - ; must be at end of file - END - diff --git a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt index 2eb522293a107..84e4b42284a52 100644 --- a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt @@ -187,8 +187,6 @@ if(CLR_CMAKE_TARGET_WIN32) set(CLRDEBUGINFO_RESOURCE_NAME CLRDEBUGINFOWINDOWSX86) elseif(CLR_CMAKE_TARGET_ARCH_ARM64) set(CLRDEBUGINFO_RESOURCE_NAME CLRDEBUGINFOWINDOWSARM64) - elseif(CLR_CMAKE_TARGET_ARCH_ARM) - set(CLRDEBUGINFO_RESOURCE_NAME CLRDEBUGINFOWINDOWSARM) endif(CLR_CMAKE_TARGET_ARCH_AMD64) add_custom_target( diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index aceb755fa5dd5..96cc1e3934ef4 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -123,7 +123,7 @@ static PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntim return pUnwindInfo; -#elif defined(TARGET_ARM) || defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) // if this function uses packed unwind data then at least one of the two least significant bits // will be non-zero. if this is the case then there will be no xdata record to enumerate. @@ -133,15 +133,9 @@ static PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntim PTR_UInt32 xdata = dac_cast(pRuntimeFunction->UnwindData + moduleBase); int size = 4; -#if defined(TARGET_ARM) - // See https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling - int unwindWords = xdata[0] >> 28; - int epilogScopes = (xdata[0] >> 23) & 0x1f; -#else // See https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling int unwindWords = xdata[0] >> 27; int epilogScopes = (xdata[0] >> 22) & 0x1f; -#endif if (unwindWords == 0 && epilogScopes == 0) { @@ -191,10 +185,6 @@ static int LookupUnwindInfoForMethod(uint32_t relativePc, int low, int high) { -#ifdef TARGET_ARM - relativePc |= THUMB_CODE; -#endif - // Binary search the RUNTIME_FUNCTION table // Use linear search once we get down to a small number of elements // to avoid Binary search overhead. @@ -504,7 +494,7 @@ uintptr_t CoffNativeCodeManager::GetConservativeUpperBoundForOutgoingArgs(Method upperBound = dac_cast(pRegisterSet->GetFP() - ((PTR_UNWIND_INFO) pUnwindDataBlob)->FrameOffset); } -#elif defined(TARGET_ARM) || defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) // Unwind the current method context to get the caller's stack pointer // and use it as the upper bound for the callee SIZE_T EstablisherFrame; @@ -733,9 +723,9 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn // Decode the GC info for the current method to determine its return type GcInfoDecoderFlags flags = DECODE_RETURN_KIND; -#if defined(TARGET_ARM) || defined(TARGET_ARM64) +#if defined(TARGET_ARM64) flags = (GcInfoDecoderFlags)(flags | DECODE_HAS_TAILCALLS); -#endif // TARGET_ARM || TARGET_ARM64 +#endif // TARGET_ARM64 GcInfoDecoder decoder(GCInfoToken(p), flags); *pRetValueKind = GetGcRefKind(decoder.GetReturnKind()); diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h index 50bbc0e85373c..445a998fdb00b 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h @@ -9,11 +9,6 @@ struct T_RUNTIME_FUNCTION { uint32_t EndAddress; uint32_t UnwindInfoAddress; }; -#elif defined(TARGET_ARM) -struct T_RUNTIME_FUNCTION { - uint32_t BeginAddress; - uint32_t UnwindData; -}; #elif defined(TARGET_ARM64) struct T_RUNTIME_FUNCTION { uint32_t BeginAddress; diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 9c3fbaff8a997..fada96c3a4a29 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -673,19 +673,6 @@ elseif(CLR_CMAKE_TARGET_ARCH_I386) ${ARCH_SOURCES_DIR}/thunktemplates.asm ) - set(VM_HEADERS_WKS_ARCH_ASM - ${ARCH_SOURCES_DIR}/asmconstants.h - ) -elseif(CLR_CMAKE_TARGET_ARCH_ARM) - set(VM_SOURCES_WKS_ARCH_ASM - ${ARCH_SOURCES_DIR}/asmhelpers.asm - ${ARCH_SOURCES_DIR}/CrtHelpers.asm - ${ARCH_SOURCES_DIR}/ehhelpers.asm - ${ARCH_SOURCES_DIR}/patchedcode.asm - ${ARCH_SOURCES_DIR}/PInvokeStubs.asm - ${ARCH_SOURCES_DIR}/thunktemplates.asm - ) - set(VM_HEADERS_WKS_ARCH_ASM ${ARCH_SOURCES_DIR}/asmconstants.h ) diff --git a/src/coreclr/vm/arm/CrtHelpers.asm b/src/coreclr/vm/arm/CrtHelpers.asm deleted file mode 100644 index fd762e74e0c39..0000000000000 --- a/src/coreclr/vm/arm/CrtHelpers.asm +++ /dev/null @@ -1,156 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -; *********************************************************************** -; File: CrtHelpers.asm -; -; *********************************************************************** - -#include "ksarm.h" - -#include "asmconstants.h" - -#include "asmmacros.h" - - TEXTAREA - -; JIT_MemSet/JIT_MemCpy -; -; It is IMPORANT that the exception handling code is able to find these guys -; on the stack, but to keep them from being tailcalled by VC++ we need to turn -; off optimization and it ends up being a wasteful implementation. -; -; Hence these assembly helpers. -; -;EXTERN_C void __stdcall JIT_MemSet(void* _dest, int c, size_t count) - LEAF_ENTRY JIT_MemSet - -; -; The memset function sets the first count bytes of -; dest to the character c (r1). -; -; Doesn't return a value -; - - subs r2, r2, #4 - blt ByteSet - - ands r1, r1, #&FF - orr r1, r1, r1, lsl #8 -CheckAlign ; 2-3 cycles - ands r3, r0, #3 ; Check alignment and fix if possible - bne Align - -BlockSet ; 6-7 cycles - orr r1, r1, r1, lsl #16 - subs r2, r2, #12 - mov r3, r1 - blt BlkSet8 - -BlkSet16 ; 7 cycles/16 bytes - stm r0!, {r1, r3} - subs r2, r2, #16 - stm r0!, {r1, r3} - bge BlkSet16 - -BlkSet8 ; 4 cycles/8 bytes - adds r2, r2, #8 - blt BlkSet4 - stm r0!, {r1, r3} - sub r2, r2, #8 - -BlkSet4 - adds r2, r2, #4 ; 4 cycles/4 bytes - blt ByteSet - str r1, [r0], #4 - b MaybeExit - -ByteSet - adds r2, r2, #4 -MaybeExit - beq ExitMemSet - - strb r1, [r0] ; 5 cycles/1-3bytes - cmp r2, #2 - blt ExitMemSet - strb r1, [r0, #1] - strbgt r1, [r0, #2] - -ExitMemSet - - bx lr - -Align ; 8 cycles/1-3 bytes - tst r0, #1 ; Check byte alignment - beq AlignHalf - subs r2, r2, #1 - strb r1, [r0], #1 -AlignHalf - tst r0, #2 ; Check Half-word alignment - beq BlockSet - subs r2, r2, #2 - strh r1, [r0], #2 - b BlockSet - - LEAF_END_MARKED JIT_MemSet - - -;EXTERN_C void __stdcall JIT_MemCpy(void* _dest, const void *_src, size_t count) - LEAF_ENTRY JIT_MemCpy -; -; It only requires 4 byte alignment -; and doesn't return a value - - cmp r2, #0 ; quick check for 0 length - beq ExitMemCpy ; if zero, exit - - tst r0, #3 ; skip directly to aligned if already aligned - beq DestAligned ; if 0, we're already aligned; go large - -ByteLoop1 - subs r2, r2, #1 ; decrement byte counter - ldrb r3, [r1], #1 ; copy one byte - strb r3, [r0], #1 - beq ExitMemCpy ; if the byte counter hits 0, exit early - tst r0, #3 ; are we aligned now? - bne ByteLoop1 ; nope, keep going - -DestAligned - subs r2, r2, #8 ; byte counter -= 8 - blt AlignedFinished ; if that puts us negative, skip the big copy - - tst r1, #3 ; is the 4-byte source aligned? - addne r2, r2, #8 ; if not, fix the byte counter (+= 8) - bne ByteLoop2 ; and do all the rest with bytes - -QwordLoop - subs r2, r2, #8 ; decrement byte counter by 8 - ldm r1!, {r3,r12} ; copy one qword - stm r0!, {r3,r12} ; - bge QwordLoop ; loop until the byte counter goes negative - -AlignedFinished - adds r2, r2, #4 ; add 4 to recover a potential >= 4-byte tail - blt AlignedFinished2 - ldr r3, [r1], #4 - str r3, [r0], #4 - b MaybeExitMemCpy -AlignedFinished2 - adds r2, r2, #4 ; add 4 more to the byte counter to recover - -MaybeExitMemCpy - beq ExitMemCpy ; the remaining count - -ByteLoop2 - subs r2, r2, #1 ; decrement the counter - ldrb r3, [r1], #1 ; copy one byte - strb r3, [r0], #1 - bne ByteLoop2 ; loop until the counter hits 0 - -ExitMemCpy - bx lr - - LEAF_END_MARKED JIT_MemCpy - - END - diff --git a/src/coreclr/vm/arm/PInvokeStubs.asm b/src/coreclr/vm/arm/PInvokeStubs.asm deleted file mode 100644 index 60209b08a5445..0000000000000 --- a/src/coreclr/vm/arm/PInvokeStubs.asm +++ /dev/null @@ -1,227 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" - -#include "asmconstants.h" - -#include "asmmacros.h" - - - IMPORT VarargPInvokeStubWorker - IMPORT GenericPInvokeCalliStubWorker - IMPORT JIT_PInvokeEndRarePath - - IMPORT s_gsCookie - IMPORT g_TrapReturningThreads - - SETALIAS InlinedCallFrame_vftable, ??_7InlinedCallFrame@@6B@ - IMPORT $InlinedCallFrame_vftable - -; ------------------------------------------------------------------ -; Macro to generate PInvoke Stubs. -; $__PInvokeStubFuncName : function which calls the actual stub obtained from VASigCookie -; $__PInvokeGenStubFuncName : function which generates the IL stubs for PInvoke -; -; Params :- -; $FuncPrefix : prefix of the function name for the stub -; Eg. VarargPinvoke, GenericPInvokeCalli -; $VASigCookieReg : register which contains the VASigCookie -; $SaveFPArgs : "Yes" or "No" . For varidic functions FP Args are not present in FP regs -; So need not save FP Args registers for vararg Pinvoke - MACRO - - PINVOKE_STUB $FuncPrefix,$VASigCookieReg,$SaveFPArgs - - GBLS __PInvokeStubFuncName - GBLS __PInvokeGenStubFuncName - GBLS __PInvokeStubWorkerName - - IF "$FuncPrefix" == "GenericPInvokeCalli" -__PInvokeStubFuncName SETS "$FuncPrefix":CC:"Helper" - ELSE -__PInvokeStubFuncName SETS "$FuncPrefix":CC:"Stub" - ENDIF -__PInvokeGenStubFuncName SETS "$FuncPrefix":CC:"GenILStub" -__PInvokeStubWorkerName SETS "$FuncPrefix":CC:"StubWorker" - - IF "$VASigCookieReg" == "r1" -__PInvokeStubFuncName SETS "$__PInvokeStubFuncName":CC:"_RetBuffArg" -__PInvokeGenStubFuncName SETS "$__PInvokeGenStubFuncName":CC:"_RetBuffArg" - ENDIF - - NESTED_ENTRY $__PInvokeStubFuncName - - ; save reg value before using the reg - PROLOG_PUSH {$VASigCookieReg} - - ; get the stub - ldr $VASigCookieReg, [$VASigCookieReg,#VASigCookie__pNDirectILStub] - - ; if null goto stub generation - cbz $VASigCookieReg, %0 - - EPILOG_STACK_FREE 4 - - EPILOG_BRANCH_REG $VASigCookieReg - -0 - - EPILOG_POP {$VASigCookieReg} - EPILOG_BRANCH $__PInvokeGenStubFuncName - - NESTED_END - - - NESTED_ENTRY $__PInvokeGenStubFuncName - - PROLOG_WITH_TRANSITION_BLOCK 0, $SaveFPArgs - - ; r2 = UnmanagedTarget\ MethodDesc - mov r2, r12 - - ; r1 = VaSigCookie - IF "$VASigCookieReg" != "r1" - mov r1, $VASigCookieReg - ENDIF - - ; r0 = pTransitionBlock - add r0, sp, #__PWTB_TransitionBlock - - ; save hidden arg - mov r4, r12 - - bl $__PInvokeStubWorkerName - - ; restore hidden arg (method desc or unmanaged target) - mov r12, r4 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - - EPILOG_BRANCH $__PInvokeStubFuncName - - NESTED_END - - MEND - - - - TEXTAREA -; ------------------------------------------------------------------ -; JIT_PInvokeBegin helper -; -; in: -; r0 = InlinedCallFrame*: pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -; before actual InlinedCallFrame data) -; - LEAF_ENTRY JIT_PInvokeBegin - - ldr r1, =s_gsCookie - ldr r1, [r1] - str r1, [r0] - add r0, r0, SIZEOF__GSCookie - - ;; r0 = pFrame - - ;; set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code) - ldr r1, =$InlinedCallFrame_vftable - str r1, [r0] - - mov r1, 0 - str r1, [r0, #InlinedCallFrame__m_Datum] - - str sp, [r0, #InlinedCallFrame__m_pCallSiteSP] - str r11, [r0, #InlinedCallFrame__m_pCalleeSavedFP] - str lr, [r0, #InlinedCallFrame__m_pCallerReturnAddress] - str r9, [r0, #InlinedCallFrame__m_pSPAfterProlog] - - ;; r1 = GetThread(), TRASHES r2 - INLINE_GETTHREAD r1, r2 - - ;; pFrame->m_Next = pThread->m_pFrame; - ldr r2, [r1, #Thread_m_pFrame] - str r2, [r0, #Frame__m_Next] - - ;; pThread->m_pFrame = pFrame; - str r0, [r1, #Thread_m_pFrame] - - ;; pThread->m_fPreemptiveGCDisabled = 0 - mov r2, 0 - str r2, [r1, #Thread_m_fPreemptiveGCDisabled] - - bx lr - - LEAF_END - -; ------------------------------------------------------------------ -; JIT_PInvokeEnd helper -; -; in: -; r0 = InlinedCallFrame* -; - LEAF_ENTRY JIT_PInvokeEnd - - add r0, r0, SIZEOF__GSCookie - - ;; r1 = GetThread(), TRASHES r2 - INLINE_GETTHREAD r1, r2 - - ;; r0 = pFrame - ;; r1 = pThread - - ;; pThread->m_fPreemptiveGCDisabled = 1 - mov r2, 1 - str r2, [r1, #Thread_m_fPreemptiveGCDisabled] - - ;; Check return trap - ldr r2, =g_TrapReturningThreads - ldr r2, [r2] - cbnz r2, RarePath - - ;; pThread->m_pFrame = pFrame->m_Next - ldr r2, [r0, #Frame__m_Next] - str r2, [r1, #Thread_m_pFrame] - - bx lr - -RarePath - b JIT_PInvokeEndRarePath - - LEAF_END - - INLINE_GETTHREAD_CONSTANT_POOL - -; ------------------------------------------------------------------ -; VarargPInvokeStub & VarargPInvokeGenILStub -; There is a separate stub when the method has a hidden return buffer arg. -; -; in: -; r0 = VASigCookie* -; r12 = MethodDesc * -; - PINVOKE_STUB VarargPInvoke, r0, {false} - - -; ------------------------------------------------------------------ -; GenericPInvokeCalliHelper & GenericPInvokeCalliGenILStub -; Helper for generic pinvoke calli instruction -; -; in: -; r4 = VASigCookie* -; r12 = Unmanaged target -; - PINVOKE_STUB GenericPInvokeCalli, r4, {true} - -; ------------------------------------------------------------------ -; VarargPInvokeStub_RetBuffArg & VarargPInvokeGenILStub_RetBuffArg -; Vararg PInvoke Stub when the method has a hidden return buffer arg -; -; in: -; r1 = VASigCookie* -; r12 = MethodDesc* -; - PINVOKE_STUB VarargPInvoke, r1, {false} - - -; Must be at very end of file - END diff --git a/src/coreclr/vm/arm/asmhelpers.asm b/src/coreclr/vm/arm/asmhelpers.asm deleted file mode 100644 index c47d56d9d8c12..0000000000000 --- a/src/coreclr/vm/arm/asmhelpers.asm +++ /dev/null @@ -1,1739 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" - -#include "asmconstants.h" - -#include "asmmacros.h" - - IMPORT JIT_InternalThrow - IMPORT JIT_WriteBarrier - IMPORT TheUMEntryPrestubWorker - IMPORT PreStubWorker - IMPORT PreStubGetMethodDescForCompactEntryPoint - IMPORT NDirectImportWorker - IMPORT VSD_ResolveWorker - -#ifdef WRITE_BARRIER_CHECK - SETALIAS g_GCShadow, ?g_GCShadow@@3PAEA - SETALIAS g_GCShadowEnd, ?g_GCShadowEnd@@3PAEA - - IMPORT g_lowest_address - IMPORT $g_GCShadow - IMPORT $g_GCShadowEnd -#endif // WRITE_BARRIER_CHECK - - -#ifdef FEATURE_COMINTEROP - IMPORT CLRToCOMWorker - IMPORT ComPreStubWorker - IMPORT COMToCLRWorker -#endif - IMPORT CallDescrWorkerUnwindFrameChainHandler - IMPORT UMEntryPrestubUnwindFrameChainHandler -#ifdef FEATURE_COMINTEROP - IMPORT ReverseComUnwindFrameChainHandler -#endif - -#ifdef FEATURE_HIJACK - IMPORT OnHijackWorker -#endif ;FEATURE_HIJACK - - IMPORT GetCurrentSavedRedirectContext - - ;; Import to support cross-moodule external method invocation in ngen images - IMPORT ExternalMethodFixupWorker - -#ifdef FEATURE_READYTORUN - IMPORT DynamicHelperWorker -#endif - - IMPORT JIT_RareDisableHelperWorker - - ;; Imports for singleDomain statics helpers - IMPORT JIT_GetSharedNonGCStaticBase_Helper - IMPORT JIT_GetSharedGCStaticBase_Helper - - TEXTAREA - -;; LPVOID __stdcall GetCurrentIP(void); - LEAF_ENTRY GetCurrentIP - mov r0, lr - bx lr - LEAF_END - -;; LPVOID __stdcall GetCurrentSP(void); - LEAF_ENTRY GetCurrentSP - mov r0, sp - bx lr - LEAF_END - -;;----------------------------------------------------------------------------- -;; This helper routine enregisters the appropriate arguments and makes the -;; actual call. -;;----------------------------------------------------------------------------- -;;void CallDescrWorkerInternal(CallDescrData * pCallDescrData); - NESTED_ENTRY CallDescrWorkerInternal,,CallDescrWorkerUnwindFrameChainHandler - PROLOG_PUSH {r4,r5,r7,lr} - PROLOG_STACK_SAVE r7 - - mov r5,r0 ; save pCallDescrData in r5 - - ldr r1, [r5,#CallDescrData__numStackSlots] - cbz r1, Ldonestack - - ;; Add frame padding to ensure frame size is a multiple of 8 (a requirement of the OS ABI). - ;; We push four registers (above) and numStackSlots arguments (below). If this comes to an odd number - ;; of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set, - ;; extend the stack another four bytes". - lsls r2, r1, #2 - and r3, r2, #4 - sub sp, sp, r3 - - ;; This loop copies numStackSlots words - ;; from [pSrcEnd-4,pSrcEnd-8,...] to [sp-4,sp-8,...] - ldr r0, [r5,#CallDescrData__pSrc] - add r0,r0,r2 -Lstackloop - ldr r2, [r0,#-4]! - str r2, [sp,#-4]! - subs r1, r1, #1 - bne Lstackloop -Ldonestack - - ;; If FP arguments are supplied in registers (r3 != NULL) then initialize all of them from the pointer - ;; given in r3. Do not use "it" since it faults in floating point even when the instruction is not executed. - ldr r3, [r5,#CallDescrData__pFloatArgumentRegisters] - cbz r3, LNoFloatingPoint - vldm r3, {s0-s15} -LNoFloatingPoint - - ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 12] - ;; into r0, ..., r3 - - ldr r4, [r5,#CallDescrData__pArgumentRegisters] - ldm r4, {r0-r3} - - CHECK_STACK_ALIGNMENT - - ;; call pTarget - ;; Note that remoting expect target in r4. - ldr r4, [r5,#CallDescrData__pTarget] - blx r4 - - ldr r3, [r5,#CallDescrData__fpReturnSize] - - ;; Save FP return value if appropriate - cbz r3, LFloatingPointReturnDone - - ;; Float return case - ;; Do not use "it" since it faults in floating point even when the instruction is not executed. - cmp r3, #4 - bne LNoFloatReturn - vmov r0, s0 - b LFloatingPointReturnDone -LNoFloatReturn - - ;; Double return case - ;; Do not use "it" since it faults in floating point even when the instruction is not executed. - cmp r3, #8 - bne LNoDoubleReturn - vmov r0, r1, s0, s1 - b LFloatingPointReturnDone -LNoDoubleReturn - - add r2, r5, #CallDescrData__returnValue - - cmp r3, #16 - bne LNoFloatHFAReturn - vstm r2, {s0-s3} - b LReturnDone -LNoFloatHFAReturn - - cmp r3, #32 - bne LNoDoubleHFAReturn - vstm r2, {d0-d3} - b LReturnDone -LNoDoubleHFAReturn - - EMIT_BREAKPOINT ; Unreachable - -LFloatingPointReturnDone - - ;; Save return value into retbuf - str r0, [r5, #(CallDescrData__returnValue + 0)] - str r1, [r5, #(CallDescrData__returnValue + 4)] - -LReturnDone - -#ifdef _DEBUG - ;; trash the floating point registers to ensure that the HFA return values - ;; won't survive by accident - vldm sp, {d0-d3} -#endif - - EPILOG_STACK_RESTORE r7 - EPILOG_POP {r4,r5,r7,pc} - - NESTED_END - -; ------------------------------------------------------------------ - -; void LazyMachStateCaptureState(struct LazyMachState *pState); - LEAF_ENTRY LazyMachStateCaptureState - - ;; marks that this is not yet valid - mov r1, #0 - str r1, [r0, #MachState__isValid] - - str lr, [r0, #LazyMachState_captureIp] - str sp, [r0, #LazyMachState_captureSp] - - add r1, r0, #LazyMachState_captureR4_R11 - stm r1, {r4-r11} - - mov pc, lr - - LEAF_END - -; void SinglecastDelegateInvokeStub(Delegate *pThis) - LEAF_ENTRY SinglecastDelegateInvokeStub - cmp r0, #0 - beq LNullThis - - ldr r12, [r0, #DelegateObject___methodPtr] - ldr r0, [r0, #DelegateObject___target] - - bx r12 - -LNullThis - mov r0, #CORINFO_NullReferenceException_ASM - b JIT_InternalThrow - - LEAF_END - -; -; r12 = UMEntryThunk* -; - NESTED_ENTRY TheUMEntryPrestub,,UMEntryPrestubUnwindFrameChainHandler - - PROLOG_PUSH {r0-r4,lr} - PROLOG_VPUSH {d0-d7} - - CHECK_STACK_ALIGNMENT - - mov r0, r12 - bl TheUMEntryPrestubWorker - - ; Record real target address in r12. - mov r12, r0 - - ; Epilog - EPILOG_VPOP {d0-d7} - EPILOG_POP {r0-r4,lr} - EPILOG_BRANCH_REG r12 - - NESTED_END - -; ------------------------------------------------------------------ - - NESTED_ENTRY ThePreStub - - PROLOG_WITH_TRANSITION_BLOCK - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - mov r1, r12 ; pMethodDesc - - bl PreStubWorker - - mov r12, r0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG r12 - - NESTED_END - -; ------------------------------------------------------------------ - - NESTED_ENTRY ThePreStubCompactARM - - ; r12 - address of compact entry point + PC_REG_RELATIVE_OFFSET - - PROLOG_WITH_TRANSITION_BLOCK - - mov r0, r12 - - bl PreStubGetMethodDescForCompactEntryPoint - - mov r12, r0 ; pMethodDesc - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - - b ThePreStub - - NESTED_END - -; ------------------------------------------------------------------ -; This method does nothing. It's just a fixed function for the debugger to put a breakpoint on. - LEAF_ENTRY ThePreStubPatch - nop -ThePreStubPatchLabel - EXPORT ThePreStubPatchLabel - bx lr - LEAF_END - -; ------------------------------------------------------------------ -; The call in ndirect import precode points to this function. - NESTED_ENTRY NDirectImportThunk - - PROLOG_PUSH {r0-r4,lr} ; Spill general argument registers, return address and - ; arbitrary register to keep stack aligned - PROLOG_VPUSH {d0-d7} ; Spill floating point argument registers - - CHECK_STACK_ALIGNMENT - - mov r0, r12 - bl NDirectImportWorker - mov r12, r0 - - EPILOG_VPOP {d0-d7} - EPILOG_POP {r0-r4,lr} - - ; If we got back from NDirectImportWorker, the MD has been successfully - ; linked. Proceed to execute the original DLL call. - EPILOG_BRANCH_REG r12 - - NESTED_END - -; ------------------------------------------------------------------ -; void ResolveWorkerAsmStub(r0, r1, r2, r3, r4:IndirectionCellAndFlags, r12:DispatchToken) -; -; The stub dispatch thunk which transfers control to VSD_ResolveWorker. - NESTED_ENTRY ResolveWorkerAsmStub - - PROLOG_WITH_TRANSITION_BLOCK - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - mov r2, r12 ; token - - ; indirection cell in r4 - should be consistent with REG_ARM_STUB_SPECIAL - bic r1, r4, #3 ; indirection cell - and r3, r4, #3 ; flags - - bl VSD_ResolveWorker - - mov r12, r0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG r12 - - NESTED_END - -; ------------------------------------------------------------------ -; void ResolveWorkerChainLookupAsmStub(r0, r1, r2, r3, r4:IndirectionCellAndFlags, r12:DispatchToken) - NESTED_ENTRY ResolveWorkerChainLookupAsmStub - - ; ARMSTUB TODO: implement chained lookup - b ResolveWorkerAsmStub - - NESTED_END - -#if defined(FEATURE_COMINTEROP) - -; ------------------------------------------------------------------ -; setStubReturnValue -; r0 - size of floating point return value (MetaSig::GetFPReturnSize()) -; r1 - pointer to the return buffer in the stub frame - LEAF_ENTRY setStubReturnValue - - cbz r0, NoFloatingPointRetVal - - ;; Float return case - ;; Do not use "it" since it faults in floating point even when the instruction is not executed. - cmp r0, #4 - bne LNoFloatRetVal - vldr s0, [r1] - bx lr -LNoFloatRetVal - - ;; Double return case - ;; Do not use "it" since it faults in floating point even when the instruction is not executed. - cmp r0, #8 - bne LNoDoubleRetVal - vldr d0, [r1] - bx lr -LNoDoubleRetVal - - cmp r0, #16 - bne LNoFloatHFARetVal - vldm r1, {s0-s3} - bx lr -LNoFloatHFARetVal - - cmp r0, #32 - bne LNoDoubleHFARetVal - vldm r1, {d0-d3} - bx lr -LNoDoubleHFARetVal - - EMIT_BREAKPOINT ; Unreachable - -NoFloatingPointRetVal - - ;; Restore the return value from retbuf - ldr r0, [r1] - ldr r1, [r1, #4] - bx lr - - LEAF_END - -#endif // FEATURE_COMINTEROP - - -#if defined(FEATURE_COMINTEROP) -; ------------------------------------------------------------------ -; Function used by remoting/COM interop to get floating point return value (since it's not in the same -; register(s) as non-floating point values). -; -; On entry; -; r0 : size of the FP result (4 or 8 bytes) -; r1 : pointer to 64-bit buffer to receive result -; -; On exit: -; buffer pointed to by r1 on entry contains the float or double argument as appropriate -; - LEAF_ENTRY getFPReturn - - cmp r0, #4 - bne LgetFP8 - vmov r2, s0 - str r2, [r1] - bx lr -LgetFP8 - vmov r2, r3, d0 - strd r2, r3, [r1] - bx lr - - LEAF_END - -; ------------------------------------------------------------------ -; Function used by remoting/COM interop to set floating point return value (since it's not in the same -; register(s) as non-floating point values). -; -; On entry: -; r0 : size of the FP result (4 or 8 bytes) -; r2/r3 : 32-bit or 64-bit FP result -; -; On exit: -; s0 : float result if r0 == 4 -; d0 : double result if r0 == 8 -; - LEAF_ENTRY setFPReturn - - cmp r0, #4 - bne LsetFP8 - vmov s0, r2 - bx lr -LsetFP8 - vmov d0, r2, r3 - bx lr - - LEAF_END - -#endif defined(FEATURE_COMINTEROP) - - -#ifdef FEATURE_COMINTEROP -; ------------------------------------------------------------------ -; GenericComPlusCallStub that erects a ComPlusMethodFrame and calls into the runtime -; (CLRToCOMWorker) to dispatch rare cases of the interface call. -; -; On entry: -; r0 : 'this' object -; r12 : Interface MethodDesc* -; plus user arguments in registers and on the stack -; -; On exit: -; r0/r1/s0/d0 set to return value of the call as appropriate -; - NESTED_ENTRY GenericComPlusCallStub - - PROLOG_WITH_TRANSITION_BLOCK ASM_ENREGISTERED_RETURNTYPE_MAXSIZE - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - mov r1, r12 ; pMethodDesc - - ; Call CLRToCOMWorker(pFrame). This call will set up the rest of the frame (including the vfptr, - ; the GS cookie and linking to the thread), make the client call and return with correct registers set - ; (r0/r1/s0-s3/d0-d3 as appropriate). - - bl CLRToCOMWorker - - ; r0 = fpRetSize - - ; return value is stored before float argument registers - add r1, sp, #(__PWTB_FloatArgumentRegisters - ASM_ENREGISTERED_RETURNTYPE_MAXSIZE) - bl setStubReturnValue - - EPILOG_WITH_TRANSITION_BLOCK_RETURN - - NESTED_END - -; ------------------------------------------------------------------ -; COM to CLR stub called the first time a particular method is invoked. -; -; On entry: -; r12 : (MethodDesc* - ComCallMethodDesc_Offset_FromR12) provided by prepad thunk -; plus user arguments in registers and on the stack -; -; On exit: -; tail calls to real method -; - NESTED_ENTRY ComCallPreStub - - GBLA ComCallPreStub_FrameSize - GBLA ComCallPreStub_FramePad - GBLA ComCallPreStub_StackAlloc - GBLA ComCallPreStub_Frame - GBLA ComCallPreStub_ErrorReturn - -; Set the defaults -ComCallPreStub_FramePad SETA 8 ; error return -ComCallPreStub_FrameSize SETA (ComCallPreStub_FramePad + SIZEOF__GSCookie + SIZEOF__ComMethodFrame) - - IF ComCallPreStub_FrameSize:MOD:8 != 0 -ComCallPreStub_FramePad SETA ComCallPreStub_FramePad + 4 -ComCallPreStub_FrameSize SETA ComCallPreStub_FrameSize + 4 - ENDIF - -ComCallPreStub_StackAlloc SETA ComCallPreStub_FrameSize - SIZEOF__ArgumentRegisters - 2 * 4 -ComCallPreStub_Frame SETA SIZEOF__FloatArgumentRegisters + ComCallPreStub_FramePad + SIZEOF__GSCookie -ComCallPreStub_ErrorReturn SETA SIZEOF__FloatArgumentRegisters - - PROLOG_PUSH {r0-r3} ; Spill general argument registers - PROLOG_PUSH {r11,lr} ; Save return address - PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc ; Alloc non-spill portion of stack frame - PROLOG_VPUSH {d0-d7} ; Spill floating point argument registers - - CHECK_STACK_ALIGNMENT - - ; Finish initializing the frame. The C++ helper will fill in the GS cookie and vfptr and link us to - ; the Thread frame chain (see ComPrestubMethodFrame::Push). That leaves us with m_pFuncDesc. - ; The prepad thunk passes us a value which is the MethodDesc* - ComCallMethodDesc_Offset_FromR12 (due to encoding limitations in the - ; thunk). So we must correct this by adding 4 before storing the pointer. - add r12, #(ComCallMethodDesc_Offset_FromR12) - str r12, [sp, #(ComCallPreStub_Frame + UnmanagedToManagedFrame__m_pvDatum)] - - ; Call the C++ worker: ComPreStubWorker(&Frame) - add r0, sp, #(ComCallPreStub_Frame) - add r1, sp, #(ComCallPreStub_ErrorReturn) - bl ComPreStubWorker - - ; Handle failure case. - cbz r0, ErrorExit - - ; Stash real target address where it won't be overwritten by restoring the calling state. - mov r12, r0 - - EPILOG_VPOP {d0-d7} ; Restore floating point argument registers - EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_POP {r11,lr} - EPILOG_POP {r0-r3} ; Restore argument registers - ; Tail call the real target. Actually ComPreStubWorker returns the address of the prepad thunk on ARM, - ; that way we don't run out of volatile registers trying to remember both the new target address and - ; the hidden MethodDesc* argument. ComPreStubWorker patched the prepad though so the second time - ; through we won't end up here again. - EPILOG_BRANCH_REG r12 - -ErrorExit - ; Failed to find a stub to call. Retrieve the return value ComPreStubWorker set for us. - ldr r0, [sp, #(ComCallPreStub_ErrorReturn)] - ldr r1, [sp, #(ComCallPreStub_ErrorReturn+4)] - EPILOG_STACK_FREE ComCallPreStub_StackAlloc + SIZEOF__FloatArgumentRegisters - EPILOG_POP {r11,lr} - EPILOG_STACK_FREE SIZEOF__ArgumentRegisters - EPILOG_RETURN - - NESTED_END - -; ------------------------------------------------------------------ -; COM to CLR stub which sets up a ComMethodFrame and calls COMToCLRWorker. -; -; On entry: -; r12 : (MethodDesc* - ComCallMethodDesc_Offset_FromR12) provided by prepad thunk -; plus user arguments in registers and on the stack -; -; On exit: -; Result in r0/r1/s0/d0 as per the real method being called -; - NESTED_ENTRY GenericComCallStub,,ReverseComUnwindFrameChainHandler - -; Calculate space needed on stack for alignment padding, a GS cookie and a ComMethodFrame (minus the last -; field, m_ReturnAddress, which we'll push explicitly). - - GBLA GenericComCallStub_FrameSize - GBLA GenericComCallStub_FramePad - GBLA GenericComCallStub_StackAlloc - GBLA GenericComCallStub_Frame - -; Set the defaults -GenericComCallStub_FramePad SETA 0 -GenericComCallStub_FrameSize SETA (GenericComCallStub_FramePad + SIZEOF__GSCookie + SIZEOF__ComMethodFrame) - - IF GenericComCallStub_FrameSize:MOD:8 != 0 -GenericComCallStub_FramePad SETA 4 -GenericComCallStub_FrameSize SETA GenericComCallStub_FrameSize + GenericComCallStub_FramePad - ENDIF - -GenericComCallStub_StackAlloc SETA GenericComCallStub_FrameSize - SIZEOF__ArgumentRegisters - 2 * 4 -GenericComCallStub_Frame SETA SIZEOF__FloatArgumentRegisters + GenericComCallStub_FramePad + SIZEOF__GSCookie - - PROLOG_PUSH {r0-r3} ; Spill general argument registers - PROLOG_PUSH {r11,lr} ; Save return address - PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc ; Alloc non-spill portion of stack frame - PROLOG_VPUSH {d0-d7} ; Spill floating point argument registers - - CHECK_STACK_ALIGNMENT - - ; Store MethodDesc* in frame. Due to a limitation of the prepad, r12 actually contains a value - ; "ComCallMethodDesc_Offset_FromR12" less than the pointer we want, so fix that up. - add r12, r12, #(ComCallMethodDesc_Offset_FromR12) - str r12, [sp, #(GenericComCallStub_Frame + UnmanagedToManagedFrame__m_pvDatum)] - - ; Call COMToCLRWorker(pThread, pFrame). Note that pThread is computed inside the method so we don't - ; need to set it up here. - ; - ; Setup R1 to point to the start of the explicit frame. We account for alignment padding and - ; space for GSCookie. - add r1, sp, #(GenericComCallStub_Frame) - bl COMToCLRWorker - - EPILOG_STACK_FREE GenericComCallStub_StackAlloc + SIZEOF__FloatArgumentRegisters - EPILOG_POP {r11,lr} - EPILOG_STACK_FREE SIZEOF__ArgumentRegisters - EPILOG_RETURN - - NESTED_END - -; ------------------------------------------------------------------ -; COM to CLR stub called from COMToCLRWorker that actually dispatches to the real managed method. -; -; On entry: -; r0 : dwStackSlots, count of argument stack slots to copy -; r1 : pFrame, ComMethodFrame pushed by GenericComCallStub above -; r2 : pTarget, address of code to call -; r3 : pSecretArg, hidden argument passed to target above in r12 -; [sp, #0] : pDangerousThis, managed 'this' reference -; -; On exit: -; Result in r0/r1/s0/d0 as per the real method being called -; - NESTED_ENTRY COMToCLRDispatchHelper,,CallDescrWorkerUnwindFrameChainHandler - - PROLOG_PUSH {r4-r5,r7,lr} - PROLOG_STACK_SAVE r7 - - ; Copy stack-based arguments. Make sure the eventual SP ends up 8-byte aligned. Note that the - ; following calculations assume that the prolog has left the stack already aligned. - CHECK_STACK_ALIGNMENT - - cbz r0, COMToCLRDispatchHelper_ArgumentsSetup - - lsl r4, r0, #2 ; r4 = (dwStackSlots * 4) - and r5, r4, #4 ; Align the stack - sub sp, sp, r5 - - add r5, r1, #SIZEOF__ComMethodFrame - add r5, r5, r4 - -COMToCLRDispatchHelper_StackLoop - ldr r4, [r5,#-4]! - str r4, [sp,#-4]! - subs r0, r0, #1 - bne COMToCLRDispatchHelper_StackLoop - - CHECK_STACK_ALIGNMENT - -COMToCLRDispatchHelper_ArgumentsSetup - ; Load floating point argument registers. - sub r4, r1, #(GenericComCallStub_Frame) - vldm r4, {d0-d7} - - ; Prepare the call target and hidden argument prior to overwriting r0-r3. - mov r12, r3 ; r12 = hidden argument - mov lr, r2 ; lr = target code - - ; Load general argument registers except r0. - add r4, r1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 4) - ldm r4, {r1-r3} - - ; Load r0 from the managed this, not the original incoming IUnknown*. - ldr r0, [r7, #(4 * 4)] - - ; Make the call. - blx lr - - EPILOG_STACK_RESTORE r7 - EPILOG_POP {r4-r5,r7,pc} - - NESTED_END - -#endif // FEATURE_COMINTEROP - -#ifdef PROFILING_SUPPORTED - -PROFILE_ENTER equ 1 -PROFILE_LEAVE equ 2 -PROFILE_TAILCALL equ 4 - - ; ------------------------------------------------------------------ - ; void JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle) - LEAF_ENTRY JIT_ProfilerEnterLeaveTailcallStub - bx lr - LEAF_END - - ; Define the layout of the PROFILE_PLATFORM_SPECIFIC_DATA we push on the stack for all profiler - ; helpers. - map 0 - field 4 ; r0 - field 4 ; r1 - field 4 ; r11 - field 4 ; Pc (caller's PC, i.e. LR) - field SIZEOF__FloatArgumentRegisters ; spilled floating point argument registers -functionId field 4 -probeSp field 4 -profiledSp field 4 -hiddenArg field 4 -flags field 4 - -SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA field 0 - -; ------------------------------------------------------------------ -; Macro used to generate profiler helpers. In all cases we push a partially initialized -; PROFILE_PLATFORM_SPECIFIC_DATA structure on the stack and call into a C++ helper to continue processing. -; -; On entry: -; r0 : clientInfo -; r1/r2 : return values (in case of leave) -; frame pointer(r11) must be set (in case of enter) -; all arguments are on stack at frame pointer (r11) + 8bytes (save lr & prev r11). -; -; On exit: -; All register values are preserved including volatile registers -; - MACRO - DefineProfilerHelper $HelperName, $Flags - - GBLS __ProfilerHelperFunc -__ProfilerHelperFunc SETS "$HelperName":CC:"Naked" - - NESTED_ENTRY $__ProfilerHelperFunc - - IMPORT $HelperName ; The C++ helper which does most of the work - - PROLOG_PUSH {r0,r3,r9,r12} ; save volatile general purpose registers. remaining r1 & r2 are saved below...saving r9 as it is required for virtualunwinding - PROLOG_STACK_ALLOC (6*4) ; Reserve space for tail end of structure (5*4 bytes) and extra 4 bytes is for aligning the stack at 8-byte boundary - PROLOG_VPUSH {d0-d7} ; Spill floting point argument registers - PROLOG_PUSH {r1,r11,lr} ; Save possible return value in r1, frame pointer and return address - PROLOG_PUSH {r2} ; Save possible return value in r0. Before calling Leave Hook Jit moves contents of r0 to r2 - ; so pushing r2 instead of r0. This push statement cannot be combined with the above push - ; as r2 gets pushed before r1. - - CHECK_STACK_ALIGNMENT - - ; Zero r1 for use clearing fields in the PROFILE_PLATFORM_SPECIFIC_DATA. - eor r1, r1 - - ; Clear functionId. - str r1, [sp, #functionId] - - ; Save caller's SP (at the point this helper was called). - add r2, sp, #(SIZEOF__PROFILE_PLATFORM_SPECIFIC_DATA + 20) - str r2, [sp, #probeSp] - - ; Save caller's SP (at the point where only argument registers have been spilled). - ldr r2, [r11] - add r2, r2, #8 ; location of arguments is at frame pointer(r11) + 8 (lr & prev frame ptr is saved before changing - str r2, [sp, #profiledSp] - - ; Clear hiddenArg. - str r1, [sp, #hiddenArg] - - ; Set flags to indicate type of helper called. - mov r1, #($Flags) - str r1, [sp, #flags] - - ; Call C++ portion of helper (<$HelperName>(clientInfo, &profilePlatformSpecificData)). - mov r1, sp - bl $HelperName - - EPILOG_POP {r2} - EPILOG_POP {r1,r11,lr} - EPILOG_VPOP {d0-d7} - EPILOG_STACK_FREE (6*4) - EPILOG_POP {r0,r3,r9,r12} - - EPILOG_RETURN - - NESTED_END - - MEND - - DefineProfilerHelper ProfileEnter, PROFILE_ENTER - DefineProfilerHelper ProfileLeave, PROFILE_LEAVE - DefineProfilerHelper ProfileTailcall, PROFILE_TAILCALL - -#endif // PROFILING_SUPPORTED - - ; - ; If a preserved register were pushed onto the stack between - ; the managed caller and the H_M_F, _R4_R11 will point to its - ; location on the stack and it would have been updated on the - ; stack by the GC already and it will be popped back into the - ; appropriate register when the appropriate epilog is run. - ; - ; Otherwise, the register is preserved across all the code - ; in this HCALL or FCALL, so we need to update those registers - ; here because the GC will have updated our copies in the - ; frame. - ; - ; So, if _R4_R11 points into the MachState, we need to update - ; the register here. That's what this macro does. - ; - - MACRO - RestoreRegMS $regIndex, $reg - - ; Incoming: - ; - ; R0 = address of MachState - ; - ; $regIndex: Index of the register (R4-R11). For R4, index is 4. - ; For R5, index is 5, and so on. - ; - ; $reg: Register name (e.g. R4, R5, etc) - ; - ; Get the address of the specified captured register from machine state - add r2, r0, #(MachState__captureR4_R11 + (($regIndex-4)*4)) - - ; Get the address of the specified preserved register from machine state - ldr r3, [r0, #(MachState___R4_R11 + (($regIndex-4)*4))] - - cmp r2, r3 - bne %FT0 - ldr $reg, [r2] -0 - - MEND - -; EXTERN_C int __fastcall HelperMethodFrameRestoreState( -; INDEBUG_COMMA(HelperMethodFrame *pFrame) -; MachState *pState -; ) - LEAF_ENTRY HelperMethodFrameRestoreState - -#ifdef _DEBUG - mov r0, r1 -#endif - - ; If machine state is invalid, then simply exit - ldr r1, [r0, #MachState__isValid] - cmp r1, #0 - beq Done - - RestoreRegMS 4, R4 - RestoreRegMS 5, R5 - RestoreRegMS 6, R6 - RestoreRegMS 7, R7 - RestoreRegMS 8, R8 - RestoreRegMS 9, R9 - RestoreRegMS 10, R10 - RestoreRegMS 11, R11 -Done - ; Its imperative that the return value of HelperMethodFrameRestoreState is zero - ; as it is used in the state machine to loop until it becomes zero. - ; Refer to HELPER_METHOD_FRAME_END macro for details. - mov r0,#0 - bx lr - - LEAF_END - -#ifdef FEATURE_HIJACK - -; ------------------------------------------------------------------ -; Hijack function for functions which return a value type - NESTED_ENTRY OnHijackTripThread - PROLOG_PUSH {r0,r4-r11,lr} - - PROLOG_VPUSH {d0-d3} ; saving as d0-d3 can have the floating point return value - PROLOG_PUSH {r1} ; saving as r1 can have partial return value when return is > 32 bits - PROLOG_STACK_ALLOC 4 ; 8 byte align - - CHECK_STACK_ALIGNMENT - - add r0, sp, #40 - bl OnHijackWorker - - EPILOG_STACK_FREE 4 - EPILOG_POP {r1} - EPILOG_VPOP {d0-d3} - - EPILOG_POP {r0,r4-r11,pc} - NESTED_END - -#endif ; FEATURE_HIJACK - -; ------------------------------------------------------------------ -; Macro to generate Redirection Stubs -; -; $reason : reason for redirection -; Eg. GCThreadControl -; NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame. -; This function is used by both the personality routine and the debugger to retrieve the original CONTEXT. - MACRO - GenerateRedirectedHandledJITCaseStub $reason - - GBLS __RedirectionStubFuncName - GBLS __RedirectionStubEndFuncName - GBLS __RedirectionFuncName -__RedirectionStubFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_Stub" -__RedirectionStubEndFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_StubEnd" -__RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thread@@CAXXZ|" - - IMPORT $__RedirectionFuncName - - NESTED_ENTRY $__RedirectionStubFuncName - - PROLOG_PUSH {r7,lr} ; return address - PROLOG_STACK_ALLOC 4 ; stack slot to save the CONTEXT * - PROLOG_STACK_SAVE r7 - - ;REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h - ;If CONTEXT is not saved at 0 offset from SP it must be changed as well. - ASSERT REDIRECTSTUB_SP_OFFSET_CONTEXT == 0 - - ; Runtime check for 8-byte alignment. This check is necessary as this function can be - ; entered before complete execution of the prolog of another function. - and r0, r7, #4 - sub sp, sp, r0 - - ; stack must be 8 byte aligned - CHECK_STACK_ALIGNMENT - - ; - ; Save a copy of the redirect CONTEXT*. - ; This is needed for the debugger to unwind the stack. - ; - bl GetCurrentSavedRedirectContext - str r0, [r7] - - ; - ; Fetch the interrupted pc and save it as our return address. - ; - ldr r1, [r0, #CONTEXT_Pc] - str r1, [r7, #8] - - ; - ; Call target, which will do whatever we needed to do in the context - ; of the target thread, and will RtlRestoreContext when it is done. - ; - bl $__RedirectionFuncName - - EMIT_BREAKPOINT ; Unreachable - -; Put a label here to tell the debugger where the end of this function is. -$__RedirectionStubEndFuncName - EXPORT $__RedirectionStubEndFuncName - - NESTED_END - - MEND - -; ------------------------------------------------------------------ -; Redirection Stub for GC in fully interruptible method - GenerateRedirectedHandledJITCaseStub GCThreadControl -; ------------------------------------------------------------------ - GenerateRedirectedHandledJITCaseStub DbgThreadControl -; ------------------------------------------------------------------ - GenerateRedirectedHandledJITCaseStub UserSuspend - -#ifdef _DEBUG -; ------------------------------------------------------------------ -; Redirection Stub for GC Stress - GenerateRedirectedHandledJITCaseStub GCStress -#endif - -; ------------------------------------------------------------------ -; Functions to probe for stack space -; Input reg r4 = amount of stack to probe for -; value of reg r4 is preserved on exit from function -; r12 is trashed -; The below two functions were copied from vctools\crt\crtw32\startup\arm\chkstk.asm - - NESTED_ENTRY checkStack - subs r12,sp,r4 - mrc p15,#0,r4,c13,c0,#2 ; get TEB * - ldr r4,[r4,#8] ; get Stack limit - bcc checkStack_neg ; if r12 is less then 0 set it to 0 -checkStack_label1 - cmp r12, r4 - bcc stackProbe ; must probe to extend guardpage if r12 is beyond stackLimit - sub r4, sp, r12 ; restore value of r4 - EPILOG_RETURN -checkStack_neg - mov r12, #0 - b checkStack_label1 - NESTED_END - - NESTED_ENTRY stackProbe - PROLOG_PUSH {r5,r6} - mov r6, r12 - bfc r6, #0, #0xc ; align down (4K) -stackProbe_loop - sub r4,r4,#0x1000 ; dec stack Limit by 4K as page size is 4K - ldr r5,[r4] ; try to read ... this should move the guard page - cmp r4,r6 - bne stackProbe_loop - EPILOG_POP {r5,r6} - EPILOG_NOP sub r4,sp,r12 - EPILOG_RETURN - NESTED_END - -;------------------------------------------------ -; JIT_RareDisableHelper -; -; The JIT expects this helper to preserve registers used for return values -; - NESTED_ENTRY JIT_RareDisableHelper - - PROLOG_PUSH {r0-r1, r11, lr} ; save integer return value - PROLOG_VPUSH {d0-d3} ; floating point return value - - CHECK_STACK_ALIGNMENT - - bl JIT_RareDisableHelperWorker - - EPILOG_VPOP {d0-d3} - EPILOG_POP {r0-r1, r11, pc} - - NESTED_END - - -; -; JIT Static access helpers for single appdomain case -; - -; ------------------------------------------------------------------ -; void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID) - - LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain - - ; If class is not initialized, bail to C++ helper - add r2, r0, #DomainLocalModule__m_pDataBlob - ldrb r2, [r2, r1] - tst r2, #1 - beq CallCppHelper1 - - bx lr - -CallCppHelper1 - ; Tail call JIT_GetSharedNonGCStaticBase_Helper - b JIT_GetSharedNonGCStaticBase_Helper - LEAF_END - - -; ------------------------------------------------------------------ -; void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID) - - LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain - - bx lr - LEAF_END - - -; ------------------------------------------------------------------ -; void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID) - - LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain - - ; If class is not initialized, bail to C++ helper - add r2, r0, #DomainLocalModule__m_pDataBlob - ldrb r2, [r2, r1] - tst r2, #1 - beq CallCppHelper3 - - ldr r0, [r0, #DomainLocalModule__m_pGCStatics] - bx lr - -CallCppHelper3 - ; Tail call Jit_GetSharedGCStaticBase_Helper - b JIT_GetSharedGCStaticBase_Helper - LEAF_END - - -; ------------------------------------------------------------------ -; void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID) - - LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain - - ldr r0, [r0, #DomainLocalModule__m_pGCStatics] - bx lr - LEAF_END - - -; ------------------------------------------------------------------ -; GC write barrier support. -; -; There's some complexity here for a couple of reasons: -; -; Firstly, there are a few variations of barrier types (input registers, checked vs unchecked, UP vs MP etc.). -; So first we define a number of helper macros that perform fundamental pieces of a barrier and then we define -; the final barrier functions by assembling these macros in various combinations. -; -; Secondly, for performance reasons we believe it's advantageous to be able to modify the barrier functions -; over the lifetime of the CLR. Specifically ARM has real problems reading the values of external globals (we -; need two memory indirections to do this) so we'd like to be able to directly set the current values of -; various GC globals (e.g. g_lowest_address and g_card_table) into the barrier code itself and then reset them -; every time they change (the GC already calls the VM to inform it of these changes). To handle this without -; creating too much fragility such as hardcoding instruction offsets in the VM update code, we wrap write -; barrier creation and GC globals access in a set of macros that create a table of descriptors describing each -; offset that must be patched. -; - -; Many of the following macros need a scratch register. Define a name for it here so it's easy to modify this -; in the future. - GBLS __wbscratch -__wbscratch SETS "r3" - -; -; First define the meta-macros used to support dynamically patching write barriers. -; - - ; WRITEBARRIERAREA - ; - ; As we assemble each write barrier function we build a descriptor for the offsets within that function - ; that need to be patched at runtime. We write these descriptors into a read-only portion of memory. Use a - ; specially-named linker section for this to ensure all the descriptors are contiguous and form a table. - ; During the final link of the CLR this section should be merged into the regular read-only data section. - ; - ; This macro handles switching assembler output to the above section (similar to the TEXTAREA or - ; RODATAAREA macros defined by kxarm.h). - ; - MACRO - WRITEBARRIERAREA - AREA |.clrwb|,DATA,READONLY - MEND - - ; BEGIN_WRITE_BARRIERS - ; - ; This macro must be invoked before any write barriers are defined. It sets up and exports a symbol, - ; g_rgWriteBarrierDescriptors, used by the VM to locate the start of the table describing the offsets in - ; each write barrier that need to be modified dynamically. - ; - MACRO - BEGIN_WRITE_BARRIERS - - ; Define a global boolean to track whether we're currently in a BEGIN_WRITE_BARRIERS section. This is - ; used purely to catch incorrect attempts to define a write barrier outside the section. - GBLL __defining_write_barriers -__defining_write_barriers SETL {true} - - ; Switch to the descriptor table section. - WRITEBARRIERAREA - - ; Define and export a symbol pointing to the start of the descriptor table. -g_rgWriteBarrierDescriptors - EXPORT g_rgWriteBarrierDescriptors - - ; Switch back to the code section. - TEXTAREA - MEND - - ; END_WRITE_BARRIERS - ; - ; This macro must be invoked after all write barriers have been defined. It finalizes the creation of the - ; barrier descriptor table by writing a sentinel value at the end. - ; - MACRO - END_WRITE_BARRIERS - - ASSERT __defining_write_barriers -__defining_write_barriers SETL {false} - - ; Switch to the descriptor table section. - WRITEBARRIERAREA - - ; Write the sentinel value to the end of the descriptor table (a function entrypoint address of zero). - DCD 0 - - ; Switch back to the code section. - TEXTAREA - MEND - - ; WRITE_BARRIER_ENTRY - ; - ; Declare the start of a write barrier function. Use similarly to NESTED_ENTRY. This is the only legal way - ; to declare a write barrier function. - ; - MACRO - WRITE_BARRIER_ENTRY $name - - ; Ensure we're called inside a BEGIN_WRITE_BARRIERS section. - ASSERT __defining_write_barriers - - ; Do the standard function declaration logic. Must use a NESTED_ENTRY since we require unwind info to - ; be registered (for the case where the barrier AVs and the runtime needs to recover). - LEAF_ENTRY $name - - ; Record the function name as it's used as the basis for unique label name creation in some of the - ; macros below. - GBLS __write_barrier_name -__write_barrier_name SETS "$name" - - ; Declare globals to collect the values of the offsets of instructions that load GC global values. - GBLA __g_lowest_address_offset - GBLA __g_highest_address_offset - GBLA __g_ephemeral_low_offset - GBLA __g_ephemeral_high_offset - GBLA __g_card_table_offset - - ; Initialize the above offsets to 0xffff. The default of zero is unsatisfactory because we could - ; legally have an offset of zero and we need some way to distinguish unset values (both for debugging - ; and because some write barriers don't use all the globals). -__g_lowest_address_offset SETA 0xffff -__g_highest_address_offset SETA 0xffff -__g_ephemeral_low_offset SETA 0xffff -__g_ephemeral_high_offset SETA 0xffff -__g_card_table_offset SETA 0xffff - - MEND - - ; WRITE_BARRIER_END - ; - ; The partner to WRITE_BARRIER_ENTRY, used like NESTED_END. - ; - MACRO - WRITE_BARRIER_END - - LTORG ; force the literal pool to be emitted here so that copy code picks it up - ; Use the standard macro to end the function definition. - LEAF_END_MARKED $__write_barrier_name - -; Define a local string to hold the name of a label identifying the end of the write barrier function. - LCLS __EndLabelName -__EndLabelName SETS "$__write_barrier_name":CC:"_End" - - ; Switch to the descriptor table section. - WRITEBARRIERAREA - - ; Emit the descripter for this write barrier. The order of these datums must be kept in sync with the - ; definition of the WriteBarrierDescriptor structure in vm\arm\stubs.cpp. - DCD $__write_barrier_name - DCD $__EndLabelName - DCD __g_lowest_address_offset - DCD __g_highest_address_offset - DCD __g_ephemeral_low_offset - DCD __g_ephemeral_high_offset - DCD __g_card_table_offset - - ; Switch back to the code section. - TEXTAREA - - MEND - - ; LOAD_GC_GLOBAL - ; - ; Used any time we want to load the value of one of the supported GC globals into a register. This records - ; the offset of the instructions used to do this (a movw/movt pair) so we can modify the actual value - ; loaded at runtime. - ; - ; Note that a given write barrier can only load a given global once (which will be compile-time asserted - ; below). - ; - MACRO - LOAD_GC_GLOBAL $regName, $globalName - - ; Map the GC global name to the name of the variable tracking the offset for this function. - LCLS __offset_name -__offset_name SETS "__$globalName._offset" - - ; Ensure that we only attempt to load this global at most once in the current barrier function (we - ; have this limitation purely because we only record one offset for each GC global). - ASSERT $__offset_name == 0xffff - - ; Define a unique name for a label we're about to define used in the calculation of the current - ; function offset. - LCLS __offset_label_name -__offset_label_name SETS "$__write_barrier_name$__offset_name" - - ; Define the label. -$__offset_label_name - - ; Write the current function offset into the tracking variable. -$__offset_name SETA ($__offset_label_name - $__FuncStartLabel) - - ; Emit the instructions which will be patched to provide the value of the GC global (we start with a - ; value of zero, so the write barriers have to be patched at least once before first use). - movw $regName, #0 - movt $regName, #0 - MEND - -; -; Now define the macros used in the bodies of write barrier implementations. -; - - ; UPDATE_GC_SHADOW - ; - ; Update the GC shadow heap to aid debugging (no-op unless WRITE_BARRIER_CHECK is defined). Assumes the - ; location being written lies on the GC heap (either we've already performed the dynamic check or this is - ; statically asserted by the JIT by calling the unchecked version of the write barrier). - ; - ; Input: - ; $ptrReg : register containing the location (in the real heap) to be updated - ; $valReg : register containing the value (an objref) to be written to the location above - ; - ; Output: - ; $__wbscratch : trashed - ; - MACRO - UPDATE_GC_SHADOW $ptrReg, $valReg -#ifdef WRITE_BARRIER_CHECK - - ; Need one additional temporary register to hold the shadow pointer. Assume r7 is OK for now (and - ; assert it). If this becomes a problem in the future the register choice can be parameterized. - LCLS pShadow -pShadow SETS "r7" - ASSERT "$ptrReg" != "$pShadow" - ASSERT "$valReg" != "$pShadow" - - push {$pShadow} - - ; Compute address of shadow heap location: - ; pShadow = g_GCShadow + ($ptrReg - g_lowest_address) - ldr $__wbscratch, =g_lowest_address - ldr $__wbscratch, [$__wbscratch] - sub $pShadow, $ptrReg, $__wbscratch - ldr $__wbscratch, =$g_GCShadow - ldr $__wbscratch, [$__wbscratch] - add $pShadow, $__wbscratch - - ; if (pShadow >= g_GCShadow) goto end - ldr $__wbscratch, =$g_GCShadowEnd - ldr $__wbscratch, [$__wbscratch] - cmp $pShadow, $__wbscratch - bhs %FT0 - - ; *pShadow = $valReg - str $valReg, [$pShadow] - - ; Ensure that the write to the shadow heap occurs before the read from the GC heap so that race - ; conditions are caught by INVALIDGCVALUE. - dmb - - ; if (*$ptrReg == $valReg) goto end - ldr $__wbscratch, [$ptrReg] - cmp $__wbscratch, $valReg - beq %FT0 - - ; *pShadow = INVALIDGCVALUE (0xcccccccd) - movw $__wbscratch, #0xcccd - movt $__wbscratch, #0xcccc - str $__wbscratch, [$pShadow] - -0 - pop {$pShadow} -#endif // WRITE_BARRIER_CHECK - MEND - - ; UPDATE_CARD_TABLE - ; - ; Update the card table as necessary (if the object reference being assigned in the barrier refers to an - ; object in the ephemeral generation). Otherwise this macro is a no-op. Assumes the location being written - ; lies on the GC heap (either we've already performed the dynamic check or this is statically asserted by - ; the JIT by calling the unchecked version of the write barrier). - ; - ; Additionally this macro can produce a uni-proc or multi-proc variant of the code. This governs whether - ; we bother to check if the card table has been updated before making our own update (on an MP system it - ; can be helpful to perform this check to avoid cache line thrashing, on an SP system the code path length - ; is more important). - ; - ; Input: - ; $ptrReg : register containing the location to be updated - ; $valReg : register containing the value (an objref) to be written to the location above - ; $mp : boolean indicating whether the code will run on an MP system - ; $postGrow : boolean: {true} for post-grow version, {false} otherwise - ; $tmpReg : additional register that can be trashed (can alias $ptrReg or $valReg if needed) - ; - ; Output: - ; $tmpReg : trashed (defaults to $ptrReg) - ; $__wbscratch : trashed - ; - MACRO - UPDATE_CARD_TABLE $ptrReg, $valReg, $mp, $postGrow, $tmpReg - ASSERT "$ptrReg" != "$__wbscratch" - ASSERT "$valReg" != "$__wbscratch" - ASSERT "$tmpReg" != "$__wbscratch" - - ; In most cases the callers of this macro are fine with scratching $ptrReg, the exception being the - ; ref write barrier, which wants to scratch $valReg instead. Ideally we could set $ptrReg as the - ; default for the $tmpReg parameter, but limitations in armasm won't allow that. Similarly it doesn't - ; seem to like us trying to redefine $tmpReg in the body of the macro. Instead we define a new local - ; string variable and set that either with the value of $tmpReg or $ptrReg if $tmpReg wasn't - ; specified. - LCLS tempReg - IF "$tmpReg" == "" -tempReg SETS "$ptrReg" - ELSE -tempReg SETS "$tmpReg" - ENDIF - - ; Check whether the value object lies in the ephemeral generations. If not we don't have to update the - ; card table. - LOAD_GC_GLOBAL $__wbscratch, g_ephemeral_low - cmp $valReg, $__wbscratch - blo %FT0 - ; Only in post grow higher generation can be beyond ephemeral segment - IF $postGrow - LOAD_GC_GLOBAL $__wbscratch, g_ephemeral_high - cmp $valReg, $__wbscratch - bhs %FT0 - ENDIF - - ; Update the card table. - LOAD_GC_GLOBAL $__wbscratch, g_card_table - add $__wbscratch, $__wbscratch, $ptrReg, lsr #10 - - ; On MP systems make sure the card hasn't already been set first to avoid thrashing cache lines - ; between CPUs. - ; @ARMTODO: Check that the conditional store doesn't unconditionally gain exclusive access to the - ; cache line anyway. Compare perf with a branch over and verify that omitting the compare on uniproc - ; machines really is a perf win. - IF $mp - ldrb $tempReg, [$__wbscratch] - cmp $tempReg, #0xff - movne $tempReg, #0xff - strbne $tempReg, [$__wbscratch] - ELSE - mov $tempReg, #0xff - strb $tempReg, [$__wbscratch] - ENDIF -0 - MEND - - ; CHECK_GC_HEAP_RANGE - ; - ; Verifies that the given value points into the GC heap range. If so the macro will fall through to the - ; following code. Otherwise (if the value points outside the GC heap) a branch to the supplied label will - ; be made. - ; - ; Input: - ; $ptrReg : register containing the location to be updated - ; $label : label branched to on a range check failure - ; - ; Output: - ; $__wbscratch : trashed - ; - MACRO - CHECK_GC_HEAP_RANGE $ptrReg, $label - ASSERT "$ptrReg" != "$__wbscratch" - - LOAD_GC_GLOBAL $__wbscratch, g_lowest_address - cmp $ptrReg, $__wbscratch - blo $label - LOAD_GC_GLOBAL $__wbscratch, g_highest_address - cmp $ptrReg, $__wbscratch - bhs $label - MEND - -; -; Finally define the write barrier functions themselves. Currently we don't provide variations that use -; different input registers. If the JIT wants this at a later stage in order to improve code quality it would -; be a relatively simple change to implement via an additional macro parameter to WRITE_BARRIER_ENTRY. -; -; The calling convention for the first batch of write barriers is: -; -; On entry: -; r0 : the destination address (LHS of the assignment) -; r1 : the object reference (RHS of the assignment) -; -; On exit: -; r0 : trashed -; $__wbscratch : trashed -; - - ; If you update any of the writebarrier be sure to update the sizes of patchable - ; writebarriers in - ; see ValidateWriteBarriers() - - ; The write barriers are macro taking arguments like - ; $name: Name of the write barrier - ; $mp: {true} for multi-proc, {false} otherwise - ; $post: {true} for post-grow version, {false} otherwise - - MACRO - JIT_WRITEBARRIER $name, $mp, $post - WRITE_BARRIER_ENTRY $name - IF $mp - dmb ; Perform a memory barrier - ENDIF - str r1, [r0] ; Write the reference - UPDATE_GC_SHADOW r0, r1 ; Update the shadow GC heap for debugging - UPDATE_CARD_TABLE r0, r1, $mp, $post ; Update the card table if necessary - bx lr - WRITE_BARRIER_END - MEND - - MACRO - JIT_CHECKEDWRITEBARRIER_SP $name, $post - WRITE_BARRIER_ENTRY $name - str r1, [r0] ; Write the reference - CHECK_GC_HEAP_RANGE r0, %F1 ; Check whether the destination is in the GC heap - UPDATE_GC_SHADOW r0, r1 ; Update the shadow GC heap for debugging - UPDATE_CARD_TABLE r0, r1, {false}, $post; Update the card table if necessary -1 - bx lr - WRITE_BARRIER_END - MEND - - MACRO - JIT_CHECKEDWRITEBARRIER_MP $name, $post - WRITE_BARRIER_ENTRY $name - CHECK_GC_HEAP_RANGE r0, %F1 ; Check whether the destination is in the GC heap - dmb ; Perform a memory barrier - str r1, [r0] ; Write the reference - UPDATE_GC_SHADOW r0, r1 ; Update the shadow GC heap for debugging - UPDATE_CARD_TABLE r0, r1, {true}, $post ; Update the card table if necessary - bx lr -1 - str r1, [r0] ; Write the reference - bx lr - WRITE_BARRIER_END - MEND - -; The ByRef write barriers have a slightly different interface: -; -; On entry: -; r0 : the destination address (object reference written here) -; r1 : the source address (points to object reference to write) -; -; On exit: -; r0 : incremented by 4 -; r1 : incremented by 4 -; r2 : trashed -; $__wbscratch : trashed -; - MACRO - JIT_BYREFWRITEBARRIER $name, $mp, $post - WRITE_BARRIER_ENTRY $name - IF $mp - dmb ; Perform a memory barrier - ENDIF - ldr r2, [r1] ; Load target object ref from source pointer - str r2, [r0] ; Write the reference to the destination pointer - CHECK_GC_HEAP_RANGE r0, %F1 ; Check whether the destination is in the GC heap - UPDATE_GC_SHADOW r0, r2 ; Update the shadow GC heap for debugging - UPDATE_CARD_TABLE r0, r2, $mp, $post, r2 ; Update the card table if necessary (trash r2 rather than r0) -1 - add r0, #4 ; Increment the destination pointer by 4 - add r1, #4 ; Increment the source pointer by 4 - bx lr - WRITE_BARRIER_END - MEND - - BEGIN_WRITE_BARRIERS - - ; There 4 versions of each write barriers. A 2x2 combination of multi-proc/single-proc and pre/post grow version - JIT_WRITEBARRIER JIT_WriteBarrier_SP_Pre, {false}, {false} - JIT_WRITEBARRIER JIT_WriteBarrier_SP_Post, {false}, {true} - JIT_WRITEBARRIER JIT_WriteBarrier_MP_Pre, {true}, {false} - JIT_WRITEBARRIER JIT_WriteBarrier_MP_Post, {true}, {true} - - JIT_CHECKEDWRITEBARRIER_SP JIT_CheckedWriteBarrier_SP_Pre, {false} - JIT_CHECKEDWRITEBARRIER_SP JIT_CheckedWriteBarrier_SP_Post, {true} - JIT_CHECKEDWRITEBARRIER_MP JIT_CheckedWriteBarrier_MP_Pre, {false} - JIT_CHECKEDWRITEBARRIER_MP JIT_CheckedWriteBarrier_MP_Post, {true} - - JIT_BYREFWRITEBARRIER JIT_ByRefWriteBarrier_SP_Pre, {false}, {false} - JIT_BYREFWRITEBARRIER JIT_ByRefWriteBarrier_SP_Post, {false}, {true} - JIT_BYREFWRITEBARRIER JIT_ByRefWriteBarrier_MP_Pre, {true}, {false} - JIT_BYREFWRITEBARRIER JIT_ByRefWriteBarrier_MP_Post, {true}, {true} - - END_WRITE_BARRIERS - - IMPORT JIT_WriteBarrier_Loc - -; ------------------------------------------------------------------ -; __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val) - LEAF_ENTRY JIT_WriteBarrier_Callable - - ; Branch to the write barrier - ldr r2, =JIT_WriteBarrier_Loc ; or R3? See targetarm.h - ldr pc, [r2] - - LEAF_END - -#ifdef FEATURE_READYTORUN - - NESTED_ENTRY DelayLoad_MethodCall_FakeProlog - - ; Match what the lazy thunk has pushed. The actual method arguments will be spilled later. - PROLOG_PUSH {r1-r3} - - ; This is where execution really starts. -DelayLoad_MethodCall - EXPORT DelayLoad_MethodCall - - PROLOG_PUSH {r0} - - PROLOG_WITH_TRANSITION_BLOCK 0x0, {true}, DoNotPushArgRegs - - ; Load the helper arguments - ldr r5, [sp,#(__PWTB_TransitionBlock+10*4)] ; pModule - ldr r6, [sp,#(__PWTB_TransitionBlock+11*4)] ; sectionIndex - ldr r7, [sp,#(__PWTB_TransitionBlock+12*4)] ; indirection - - ; Spill the actual method arguments - str r1, [sp,#(__PWTB_TransitionBlock+10*4)] - str r2, [sp,#(__PWTB_TransitionBlock+11*4)] - str r3, [sp,#(__PWTB_TransitionBlock+12*4)] - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - - mov r1, r7 ; pIndirection - mov r2, r6 ; sectionIndex - mov r3, r5 ; pModule - - bl ExternalMethodFixupWorker - - ; mov the address we patched to in R12 so that we can tail call to it - mov r12, r0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - - PATCH_LABEL ExternalMethodFixupPatchLabel - EPILOG_BRANCH_REG r12 - - NESTED_END - - - MACRO - DynamicHelper $frameFlags, $suffix - - GBLS __FakePrologName -__FakePrologName SETS "DelayLoad_Helper":CC:"$suffix":CC:"_FakeProlog" - - NESTED_ENTRY $__FakePrologName - - ; Match what the lazy thunk has pushed. The actual method arguments will be spilled later. - PROLOG_PUSH {r1-r3} - - GBLS __RealName -__RealName SETS "DelayLoad_Helper":CC:"$suffix" - - ; This is where execution really starts. -$__RealName - EXPORT $__RealName - - PROLOG_PUSH {r0} - - PROLOG_WITH_TRANSITION_BLOCK 0x4, {false}, DoNotPushArgRegs - - ; Load the helper arguments - ldr r5, [sp,#(__PWTB_TransitionBlock+10*4)] ; pModule - ldr r6, [sp,#(__PWTB_TransitionBlock+11*4)] ; sectionIndex - ldr r7, [sp,#(__PWTB_TransitionBlock+12*4)] ; indirection - - ; Spill the actual method arguments - str r1, [sp,#(__PWTB_TransitionBlock+10*4)] - str r2, [sp,#(__PWTB_TransitionBlock+11*4)] - str r3, [sp,#(__PWTB_TransitionBlock+12*4)] - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - - mov r1, r7 ; pIndirection - mov r2, r6 ; sectionIndex - mov r3, r5 ; pModule - - mov r4, $frameFlags - str r4, [sp,#0] - - bl DynamicHelperWorker - - cbnz r0, %FT0 - ldr r0, [sp,#(__PWTB_TransitionBlock+9*4)] ; The result is stored in the argument area of the transition block - - EPILOG_WITH_TRANSITION_BLOCK_RETURN - -0 - mov r12, r0 - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG r12 - - NESTED_END - - MEND - - DynamicHelper DynamicHelperFrameFlags_Default - DynamicHelper DynamicHelperFrameFlags_ObjectArg, _Obj - DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj - -#endif // FEATURE_READYTORUN - -;;----------------------------------------------------------------------------- -;; The following helper will access ("probe") a word on each page of the stack -;; starting with the page right beneath sp down to the one pointed to by r4. -;; The procedure is needed to make sure that the "guard" page is pushed down below the allocated stack frame. -;; The call to the helper will be emitted by JIT in the function/funclet prolog when stack frame is larger than an OS page. -;;----------------------------------------------------------------------------- -; On entry: -; r4 - points to the lowest address on the stack frame being allocated (i.e. [InitialSp - FrameSize]) -; sp - points to some byte on the last probed page -; On exit: -; r4 - is preserved -; r5 - is not preserved -; -; NOTE: this helper will probe at least one page below the one pointed to by sp. -#define PROBE_PAGE_SIZE 4096 -#define PROBE_PAGE_SIZE_LOG2 12 - - LEAF_ENTRY JIT_StackProbe - PROLOG_PUSH {r7} - PROLOG_STACK_SAVE r7 - - mov r5, sp ; r5 points to some byte on the last probed page - bfc r5, #0, #PROBE_PAGE_SIZE_LOG2 ; r5 points to the **lowest address** on the last probed page - mov sp, r5 - -ProbeLoop - ; Immediate operand for the following instruction can not be greater than 4095. - sub sp, #(PROBE_PAGE_SIZE - 4) ; sp points to the **fourth** byte on the **next page** to probe - ldr r5, [sp, #-4]! ; sp points to the lowest address on the **last probed** page - cmp sp, r4 - bhi ProbeLoop ; if (sp > r4), then we need to probe at least one more page. - - EPILOG_STACK_RESTORE r7 - EPILOG_POP {r7} - EPILOG_BRANCH_REG lr - LEAF_END_MARKED JIT_StackProbe - -#ifdef FEATURE_TIERED_COMPILATION - - IMPORT OnCallCountThresholdReached - - NESTED_ENTRY OnCallCountThresholdReachedStub - PROLOG_WITH_TRANSITION_BLOCK - - add r0, sp, #__PWTB_TransitionBlock ; TransitionBlock * - mov r1, r12 ; stub-identifying token - bl OnCallCountThresholdReached - mov r12, r0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG r12 - NESTED_END - -#endif ; FEATURE_TIERED_COMPILATION - -; Must be at very end of file - END diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h index 1017052e8ab9e..aeb620718fe5c 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -32,10 +32,6 @@ struct ArgLocDesc; extern PCODE GetPreStubEntryPoint(); -#ifndef TARGET_UNIX -#define USE_REDIRECT_FOR_GCSTRESS -#endif // TARGET_UNIX - // CPU-dependent functions Stub * GenerateInitPInvokeFrameHelper(); @@ -48,10 +44,6 @@ EXTERN_C void checkStack(void); //********************************************************************** #define COMMETHOD_PREPAD 12 // # extra bytes to allocate in addition to sizeof(ComCallMethodDesc) -#ifdef FEATURE_COMINTEROP -#define COMMETHOD_CALL_PRESTUB_SIZE 12 -#define COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET 8 // the offset of the call target address inside the prestub -#endif // FEATURE_COMINTEROP #define STACK_ALIGN_SIZE 4 @@ -229,10 +221,6 @@ inline void ClearITState(T_CONTEXT *context) { context->Cpsr = context->Cpsr & 0xf9ff03ff; } -#ifdef FEATURE_COMINTEROP -void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMethodRW, PCODE target); -#endif // FEATURE_COMINTEROP - //------------------------------------------------------------------------ inline void emitUnconditionalBranchThumb(LPBYTE pBuffer, int16_t offset) { diff --git a/src/coreclr/vm/arm/ehhelpers.asm b/src/coreclr/vm/arm/ehhelpers.asm deleted file mode 100644 index e0d17f15eb4d6..0000000000000 --- a/src/coreclr/vm/arm/ehhelpers.asm +++ /dev/null @@ -1,153 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" - -#include "asmconstants.h" - -#include "asmmacros.h" - - IMPORT HijackHandler - IMPORT ThrowControlForThread - -; -; WARNING!! These functions immediately ruin thread unwindability. This is -; WARNING!! OK as long as there is a mechanism for saving the thread context -; WARNING!! prior to running these functions as well as a mechanism for -; WARNING!! restoring the context prior to any stackwalk. This means that -; WARNING!! we need to ensure that no GC can occur while the stack is -; WARNING!! unwalkable. This further means that we cannot allow any exception -; WARNING!! to occur when the stack is unwalkable -; - - TEXTAREA - - ; GSCookie, scratch area - GBLA OFFSET_OF_FRAME - - ; GSCookie + alignment padding -OFFSET_OF_FRAME SETA 4 + SIZEOF__GSCookie - - MACRO - GenerateRedirectedStubWithFrame $STUB, $TARGET - - ; - ; This is the primary function to which execution will be redirected to. - ; - NESTED_ENTRY $STUB - - ; - ; IN: lr: original IP before redirect - ; - - PROLOG_PUSH {r4,r7,lr} - PROLOG_STACK_ALLOC OFFSET_OF_FRAME + SIZEOF__FaultingExceptionFrame - - ; At this point, the stack maybe misaligned if the thread abort was asynchronously - ; triggered in the prolog or epilog of the managed method. For such a case, we must - ; align the stack before calling into the VM. - ; - ; Runtime check for 8-byte alignment. - PROLOG_STACK_SAVE r7 - and r0, r7, #4 - sub sp, sp, r0 - - ; Save pointer to FEF for GetFrameFromRedirectedStubStackFrame - add r4, sp, #OFFSET_OF_FRAME - - ; Prepare to initialize to NULL - mov r1,#0 - str r1, [r4] ; Initialize vtbl (it is not strictly necessary) - str r1, [r4, #FaultingExceptionFrame__m_fFilterExecuted] ; Initialize BOOL for personality routine - - mov r0, r4 ; move the ptr to FEF in R0 - - ; stack must be 8 byte aligned - CHECK_STACK_ALIGNMENT - - bl $TARGET - - ; Target should not return. - EMIT_BREAKPOINT - - NESTED_END $STUB - - MEND - -; ------------------------------------------------------------------ -; -; Helpers for ThreadAbort exceptions -; - - NESTED_ENTRY RedirectForThreadAbort2,,HijackHandler - PROLOG_PUSH {r0, lr} - - ; stack must be 8 byte aligned - CHECK_STACK_ALIGNMENT - - ; On entry: - ; - ; R0 = Address of FaultingExceptionFrame. - ; - ; Invoke the helper to setup the FaultingExceptionFrame and raise the exception - bl ThrowControlForThread - - ; ThrowControlForThread doesn't return. - EMIT_BREAKPOINT - - NESTED_END RedirectForThreadAbort2 - - GenerateRedirectedStubWithFrame RedirectForThreadAbort, RedirectForThreadAbort2 - -; ------------------------------------------------------------------ - - ; This helper enables us to call into a funclet after applying the non-volatiles - NESTED_ENTRY CallEHFunclet - - PROLOG_PUSH {r4-r11, lr} - PROLOG_STACK_ALLOC 4 - - ; On entry: - ; - ; R0 = throwable - ; R1 = PC to invoke - ; R2 = address of R4 register in CONTEXT record; used to restore the non-volatile registers of CrawlFrame - ; R3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. - ; - ; Save the SP of this function - str sp, [r3] - ; apply the non-volatiles corresponding to the CrawlFrame - ldm r2, {r4-r11} - ; Invoke the funclet - blx r1 - - EPILOG_STACK_FREE 4 - EPILOG_POP {r4-r11, pc} - - NESTED_END CallEHFunclet - - ; This helper enables us to call into a filter funclet by passing it the CallerSP to lookup the - ; frame pointer for accessing the locals in the parent method. - NESTED_ENTRY CallEHFilterFunclet - - PROLOG_PUSH {lr} - PROLOG_STACK_ALLOC 4 - - ; On entry: - ; - ; R0 = throwable - ; R1 = SP of the caller of the method/funclet containing the filter - ; R2 = PC to invoke - ; R3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. - ; - ; Save the SP of this function - str sp, [r3] - ; Invoke the filter funclet - blx r2 - - EPILOG_STACK_FREE 4 - EPILOG_POP {pc} - - NESTED_END CallEHFilterFunclet - END - diff --git a/src/coreclr/vm/arm/patchedcode.asm b/src/coreclr/vm/arm/patchedcode.asm deleted file mode 100644 index 3228829f3f604..0000000000000 --- a/src/coreclr/vm/arm/patchedcode.asm +++ /dev/null @@ -1,61 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" - -#include "asmconstants.h" - -#include "asmmacros.h" - - - TEXTAREA - - -; ------------------------------------------------------------------ -; Start of the writeable code region - LEAF_ENTRY JIT_PatchedCodeStart - bx lr - LEAF_END - -; ------------------------------------------------------------------ -; GC write barrier support. -; -; GC Write barriers are defined in asmhelpers.asm. The following functions are used to define -; patchable location where the write-barriers are copied over at runtime - - LEAF_ENTRY JIT_PatchedWriteBarrierStart - ; Cannot be empty function to prevent LNK1223 - bx lr - LEAF_END - - ; These write barriers are overwritten on the fly - ; See ValidateWriteBarriers on how the sizes of these should be calculated - ALIGN 4 - LEAF_ENTRY JIT_WriteBarrier - SPACE (0x84) - LEAF_END_MARKED JIT_WriteBarrier - - ALIGN 4 - LEAF_ENTRY JIT_CheckedWriteBarrier - SPACE (0x9C) - LEAF_END_MARKED JIT_CheckedWriteBarrier - - ALIGN 4 - LEAF_ENTRY JIT_ByRefWriteBarrier - SPACE (0xA0) - LEAF_END_MARKED JIT_ByRefWriteBarrier - - LEAF_ENTRY JIT_PatchedWriteBarrierLast - ; Cannot be empty function to prevent LNK1223 - bx lr - LEAF_END - -; ------------------------------------------------------------------ -; End of the writeable code region - LEAF_ENTRY JIT_PatchedCodeLast - bx lr - LEAF_END - - -; Must be at very end of file - END diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 750972f51e984..634eea810a31d 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -280,13 +280,8 @@ void StubLinkerCPU::Init(void) // value of the global into a register. struct WriteBarrierDescriptor { -#ifdef TARGET_UNIX DWORD m_funcStartOffset; // Offset to the start of the barrier function relative to this struct address DWORD m_funcEndOffset; // Offset to the end of the barrier function relative to this struct address -#else // TARGET_UNIX - BYTE * m_pFuncStart; // Pointer to the start of the barrier function - BYTE * m_pFuncEnd; // Pointer to the end of the barrier function -#endif // TARGET_UNIX DWORD m_dw_g_lowest_address_offset; // Offset of the instruction reading g_lowest_address DWORD m_dw_g_highest_address_offset; // Offset of the instruction reading g_highest_address DWORD m_dw_g_ephemeral_low_offset; // Offset of the instruction reading g_ephemeral_low @@ -440,21 +435,12 @@ void UpdateGCWriteBarriers(bool postGrow = false) // Iterate through the write barrier patch table created in the .clrwb section // (see write barrier asm code) WriteBarrierDescriptor * pDesc = &g_rgWriteBarrierDescriptors; -#ifdef TARGET_UNIX while (pDesc->m_funcStartOffset) -#else // TARGET_UNIX - while (pDesc->m_pFuncStart) -#endif // TARGET_UNIX { // If the write barrier is being currently used (as in copied over to the patchable site) // then read the patch location from the table and use the offset to patch the target asm code -#ifdef TARGET_UNIX PBYTE to = FindWBMapping((BYTE *)pDesc + pDesc->m_funcStartOffset); size_t barrierSize = pDesc->m_funcEndOffset - pDesc->m_funcStartOffset; -#else // TARGET_UNIX - PBYTE to = FindWBMapping(pDesc->m_pFuncStart); - size_t barrierSize = pDesc->m_pFuncEnd - pDesc->m_pFuncStart; -#endif // TARGET_UNIX if(to) { to = (PBYTE)PCODEToPINSTR((PCODE)GetWriteBarrierCodeLocation(to)); @@ -564,9 +550,6 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, do { -#ifndef TARGET_UNIX - pvControlPc = Thread::VirtualUnwindCallFrame(&ctx, &nonVolRegPtrs); -#else // !TARGET_UNIX #ifdef DACCESS_COMPILE HRESULT hr = DacVirtualUnwind(threadId, &ctx, &nonVolRegPtrs); if (FAILED(hr)) @@ -582,7 +565,6 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, } #endif // DACCESS_COMPILE pvControlPc = GetIP(&ctx); -#endif // !TARGET_UNIX if (funCallDepth > 0) { --funCallDepth; @@ -1141,21 +1123,17 @@ Stub *GenerateInitPInvokeFrameHelper() ThumbReg regScratch = ThumbReg(6); ThumbReg regR9 = ThumbReg(9); -#ifdef TARGET_UNIX // Erect frame to perform call to GetThread psl->ThumbEmitProlog(1, sizeof(ArgumentRegisters), FALSE); // Save r4 for aligned stack // Save argument registers around the GetThread call. Don't bother with using ldm/stm since this inefficient path anyway. for (int reg = 0; reg < 4; reg++) psl->ThumbEmitStoreRegIndirect(ThumbReg(reg), thumbRegSp, offsetof(ArgumentRegisters, r) + sizeof(*ArgumentRegisters::r) * reg); -#endif psl->ThumbEmitGetThread(regThread); -#ifdef TARGET_UNIX for (int reg = 0; reg < 4; reg++) psl->ThumbEmitLoadRegIndirect(ThumbReg(reg), thumbRegSp, offsetof(ArgumentRegisters, r) + sizeof(*ArgumentRegisters::r) * reg); -#endif // mov [regFrame + FrameInfo.offsetOfGSCookie], GetProcessGSCookie() psl->ThumbEmitMovConstant(regScratch, GetProcessGSCookie()); @@ -1180,27 +1158,16 @@ Stub *GenerateInitPInvokeFrameHelper() psl->ThumbEmitMovConstant(regScratch, 0); psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfReturnAddress - negSpace); -#ifdef TARGET_UNIX DWORD cbSavedRegs = sizeof(ArgumentRegisters) + 2 * 4; // r0-r3, r4, lr psl->ThumbEmitAdd(regScratch, thumbRegSp, cbSavedRegs); psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfCallSiteSP - negSpace); -#else - // str SP, [regFrame + FrameInfo.offsetOfCallSiteSP] - psl->ThumbEmitStoreRegIndirect(thumbRegSp, regFrame, FrameInfo.offsetOfCallSiteSP - negSpace); -#endif // mov [regThread + offsetof(Thread, m_pFrame)], regFrame psl->ThumbEmitStoreRegIndirect(regFrame, regThread, offsetof(Thread, m_pFrame)); // leave current Thread in R4 -#ifdef TARGET_UNIX psl->ThumbEmitEpilog(); -#else - // Return. The return address has been restored into LR at this point. - // bx lr - psl->ThumbEmitJumpRegister(thumbRegLr); -#endif // A single process-wide stub that will never unload RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap()); @@ -1208,8 +1175,6 @@ Stub *GenerateInitPInvokeFrameHelper() void StubLinkerCPU::ThumbEmitGetThread(ThumbReg dest) { -#ifdef TARGET_UNIX - ThumbEmitMovConstant(ThumbReg(0), (TADDR)GetThreadHelper); ThumbEmitCallRegister(ThumbReg(0)); @@ -1218,20 +1183,6 @@ void StubLinkerCPU::ThumbEmitGetThread(ThumbReg dest) { ThumbEmitMovRegReg(dest, ThumbReg(0)); } - -#else // TARGET_UNIX - - // mrc p15, 0, dest, c13, c0, 2 - Emit16(0xee1d); - Emit16((WORD)(0x0f50 | (dest << 12))); - - ThumbEmitLoadRegIndirect(dest, dest, offsetof(TEB, ThreadLocalStoragePointer)); - - ThumbEmitLoadRegIndirect(dest, dest, sizeof(void *) * _tls_index); - - ThumbEmitLoadRegIndirect(dest, dest, (int)Thread::GetOffsetOfThreadStatic(&gCurrentThreadInfo)); - -#endif // TARGET_UNIX } @@ -1819,34 +1770,6 @@ VOID ResetCurrentContext() #endif // !DACCESS_COMPILE -#ifdef FEATURE_COMINTEROP -void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMethodRW, PCODE target) -{ - WRAPPER_NO_CONTRACT; - - // mov r12, pc - // ldr pc, [pc, #0] - // dcd 0 - // dcd target - WORD rgCode[] = { - 0x46fc, - 0xf8df, 0xf004 - }; - - BYTE *pBufferRX = (BYTE*)pCOMMethodRX - COMMETHOD_CALL_PRESTUB_SIZE; - BYTE *pBufferRW = (BYTE*)pCOMMethodRW - COMMETHOD_CALL_PRESTUB_SIZE; - - memcpy(pBufferRW, rgCode, sizeof(rgCode)); - *((PCODE*)(pBufferRW + sizeof(rgCode) + 2)) = target; - - // Ensure that the updated instructions get actually written - ClrFlushInstructionCache(pBufferRX, COMMETHOD_CALL_PRESTUB_SIZE); - - _ASSERTE(IS_ALIGNED(pBufferRX + COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET, sizeof(void*)) && - *((PCODE*)(pBufferRX + COMMETHOD_CALL_PRESTUB_ADDRESS_OFFSET)) == target); -} -#endif // FEATURE_COMINTEROP - void MovRegImm(BYTE* p, int reg, TADDR imm) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/arm/thunktemplates.asm b/src/coreclr/vm/arm/thunktemplates.asm deleted file mode 100644 index 6562be72146c2..0000000000000 --- a/src/coreclr/vm/arm/thunktemplates.asm +++ /dev/null @@ -1,43 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -#include "ksarm.h" -#include "asmconstants.h" -#include "asmmacros.h" - - - TEXTAREA - - ALIGN 4 - - #define DATA_SLOT(stub, field) stub##Code + PAGE_SIZE + stub##Data__##field - - LEAF_ENTRY StubPrecodeCode - ldr r12, DATA_SLOT(StubPrecode, MethodDesc) - ldr pc, DATA_SLOT(StubPrecode, Target) - LEAF_END_MARKED StubPrecodeCode - - ALIGN 4 - - LEAF_ENTRY FixupPrecodeCode - ldr pc, DATA_SLOT(FixupPrecode, Target) - ldr r12, DATA_SLOT(FixupPrecode, MethodDesc) - ldr pc, DATA_SLOT(FixupPrecode, PrecodeFixupThunk) - LEAF_END_MARKED FixupPrecodeCode - - ALIGN 4 - - LEAF_ENTRY CallCountingStubCode - push {r0} - ldr r12, DATA_SLOT(CallCountingStub, RemainingCallCountCell) - ldrh r0, [r12] - subs r0, r0, #1 - strh r0, [r12] - pop {r0} - beq CountReachedZero - ldr pc, DATA_SLOT(CallCountingStub, TargetForMethod) -CountReachedZero - ldr pc, DATA_SLOT(CallCountingStub, TargetForThresholdReached) - LEAF_END_MARKED CallCountingStubCode - - END diff --git a/src/native/corehost/apphost/standalone/CMakeLists.txt b/src/native/corehost/apphost/standalone/CMakeLists.txt index a002464614770..b682fd9ebaed8 100644 --- a/src/native/corehost/apphost/standalone/CMakeLists.txt +++ b/src/native/corehost/apphost/standalone/CMakeLists.txt @@ -48,7 +48,7 @@ if(CLR_CMAKE_TARGET_WIN32) ) endif() -# Specify non-default Windows libs to be used for Arm/Arm64 builds -if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) +# Specify non-default Windows libs to be used for Arm64 builds +if (CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_ARM64) target_link_libraries(apphost PRIVATE shell32.lib) endif() diff --git a/src/native/corehost/build.cmd b/src/native/corehost/build.cmd index 470746f4dde9f..e43bcae3cf3cc 100644 --- a/src/native/corehost/build.cmd +++ b/src/native/corehost/build.cmd @@ -30,7 +30,6 @@ if /i [%1] == [Checked] (set CMAKE_BUILD_TYPE=Checked&&shift&goto Arg_Loop) if /i [%1] == [AnyCPU] (set __BuildArch=x64&&shift&goto Arg_Loop) if /i [%1] == [x86] (set __BuildArch=x86&&shift&goto Arg_Loop) -if /i [%1] == [arm] (set __BuildArch=arm&&shift&goto Arg_Loop) if /i [%1] == [x64] (set __BuildArch=x64&&shift&goto Arg_Loop) if /i [%1] == [amd64] (set __BuildArch=x64&&shift&goto Arg_Loop) if /i [%1] == [arm64] (set __BuildArch=arm64&&shift&goto Arg_Loop) @@ -94,7 +93,6 @@ if not exist "%__IntermediatesDir%" md "%__IntermediatesDir%" if /i "%__BuildArch%" == "x64" (set cm_BaseRid=win7) if /i "%__BuildArch%" == "x86" (set cm_BaseRid=win7) -if /i "%__BuildArch%" == "arm" (set cm_BaseRid=win8) if /i "%__BuildArch%" == "arm64" (set cm_BaseRid=win10) :: Form the base RID to be used if we are doing a portable build if /i "%__PortableBuild%" == "1" (set cm_BaseRid=win) diff --git a/src/native/corehost/ijwhost/CMakeLists.txt b/src/native/corehost/ijwhost/CMakeLists.txt index 6a4fdbb4d4ce1..1661f162974d5 100644 --- a/src/native/corehost/ijwhost/CMakeLists.txt +++ b/src/native/corehost/ijwhost/CMakeLists.txt @@ -32,7 +32,7 @@ add_definitions(-DFEATURE_LIBHOST=1) convert_to_absolute_path(SOURCES ${SOURCES}) convert_to_absolute_path(ASM_HELPERS_SOURCES ${ASM_HELPERS_SOURCES}) -if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) +if (CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_ARM64) preprocess_files(ASM_HELPERS_SOURCES ${ASM_HELPERS_SOURCES}) if (CMAKE_GENERATOR MATCHES "Visual Studio") compile_asm(TARGET ijwhost ASM_FILES ${ASM_HELPERS_SOURCES} OUTPUT_OBJECTS ASM_HELPERS_SOURCES) @@ -47,8 +47,8 @@ list(APPEND SOURCES ${ASM_HELPERS_SOURCES}) include(../lib.cmake) -# Specify non-default Windows libs to be used for Arm/Arm64 builds -if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) +# Specify non-default Windows libs to be used for Arm64 builds +if (CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_ARM64) target_link_libraries(ijwhost PRIVATE Ole32.lib) endif() diff --git a/src/native/corehost/ijwhost/arm/asmhelpers.asm b/src/native/corehost/ijwhost/arm/asmhelpers.asm deleted file mode 100644 index 8c3d306579a94..0000000000000 --- a/src/native/corehost/ijwhost/arm/asmhelpers.asm +++ /dev/null @@ -1,41 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. -; - -#include "ksarm.h" - - TEXTAREA - - EXTERN start_runtime_and_get_target_address - - ;; Common code called from a bootstrap_thunk to call start_runtime_and_get_target_address and obtain the - ;; real target address to which to tail call. - ;; - ;; On entry: - ;; r12 : parameter provided by the thunk that points back into the thunk itself - ;; other argument registers and possibly stack locations set up ready to make the real call - ;; - ;; On exit: - ;; tail calls to the real target method - ;; - CFG_ALIGN - NESTED_ENTRY start_runtime_thunk_stub - - PROLOG_PUSH {r0-r3} ; Save general argument registers - PROLOG_PUSH {r4,lr} ; Save return address (r4 is saved simply to preserve stack alignment) - PROLOG_VPUSH {d0-d7} ; Save floating point argument registers - - mov r0, r12 ; Only argument to start_runtime_and_get_target_address is the hidden thunk parameter - bl start_runtime_and_get_target_address - - mov r12, r0 ; Preserve result (real target address) - - EPILOG_VPOP {d0-d7} ; Restore floating point argument registers - EPILOG_POP {r4,lr} ; Restore return address - EPILOG_POP {r0-r3} ; Restore general argument registers - - EPILOG_BRANCH_REG r12 ; Tail call to real target - - NESTED_END - - END diff --git a/src/native/corehost/ijwhost/arm/bootstrap_thunk.cpp b/src/native/corehost/ijwhost/arm/bootstrap_thunk.cpp deleted file mode 100644 index a8b47becfb8b5..0000000000000 --- a/src/native/corehost/ijwhost/arm/bootstrap_thunk.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "bootstrap_thunk.h" -#include "corhdr.h" -#include "pal.h" - -//================================================================================= -// Get thunk from the address that the thunk code provided -bootstrap_thunk *bootstrap_thunk::get_thunk_from_cookie(std::uintptr_t cookie) -{ - - // Cookie is generated via the first thunk instruction: - // mov r12, pc - // The pc is returned from the hardware as the pc at the start of the instruction (i.e. the thunk address) - // + 4. So we can recover the thunk address simply by subtracting 4 from the cookie. - return (bootstrap_thunk *)(cookie - 4); -} - -//================================================================================= -// Get thunk from the thunk code entry point address -bootstrap_thunk *bootstrap_thunk::get_thunk_from_entrypoint(std::uintptr_t entryAddr) -{ - // The entry point is at the start of the thunk but the code address will have the low-order bit set to - // indicate Thumb code and we need to mask that out. - return (bootstrap_thunk *)(entryAddr & ~1); -} - -//================================================================================= -// Returns the slot address of the vtable entry for this thunk -std::uintptr_t *bootstrap_thunk::get_slot_address() -{ - return m_slot; -} - -//================================================================================= -// Returns the pal::dll_t for this thunk's module -pal::dll_t bootstrap_thunk::get_dll_handle() -{ - return m_dll; -} - -//================================================================================= -// Returns the token of this thunk -std::uint32_t bootstrap_thunk::get_token() -{ - return m_token; -} - -//================================================================================= -std::uintptr_t bootstrap_thunk::get_entrypoint() -{ - // Set the low-order bit of the address returned to indicate to the hardware that it's Thumb code. - return (std::uintptr_t)this | 1; -} - -//================================================================================= -// Initializes the thunk to point to the bootstrap helper that will load the -// runtime and perform the real thunk initialization. -// -void bootstrap_thunk::initialize(std::uintptr_t pThunkInitFcn, - pal::dll_t dll, - std::uint32_t token, - std::uintptr_t *pSlot) -{ - - // Initialize code section of the thunk: - WORD rgCode[] = { - 0x46fc, // mov r12, pc - 0xf8df, 0xf004, // ldr pc, [pc, #4] - 0x0000 // padding for 4-byte alignment of target address that follows - }; - BYTE *pCode = (BYTE*)this; - memcpy(pCode, rgCode, sizeof(rgCode)); - pCode += sizeof(rgCode); - *(std::uintptr_t*)pCode = pThunkInitFcn; - - m_dll = dll; - m_slot = pSlot; - m_token = token; -} diff --git a/src/native/corehost/ijwhost/arm/bootstrap_thunk.h b/src/native/corehost/ijwhost/arm/bootstrap_thunk.h deleted file mode 100644 index 2ce6cd5ac436d..0000000000000 --- a/src/native/corehost/ijwhost/arm/bootstrap_thunk.h +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef IJW_BOOTSTRAP_THUNK_H -#define IJW_BOOTSTRAP_THUNK_H - -#if !defined(TARGET_ARM) -#error "This file should only be included on arm builds." -#endif - -#include "pal.h" -#include "corhdr.h" - -extern "C" void start_runtime_thunk_stub(); - -#include -//================================================================================= -class bootstrap_thunk -{ -private: - WORD m_rgCode[4]; - std::uintptr_t m_pBootstrapCode; - - pal::dll_t m_dll; // pal::dll_t of this module - std::uintptr_t* m_slot; // VTable slot for this thunk - std::uint32_t m_token; // Token for this thunk - -public: - // Get thunk from the address that the thunk code provided - static bootstrap_thunk *get_thunk_from_cookie(std::uintptr_t cookie); - - // Get thunk from the thunk code entry point address - static bootstrap_thunk *get_thunk_from_entrypoint(std::uintptr_t entryAddr); - - // Initializes the thunk to point to pThunkInitFcn that will load the - // runtime and perform the real thunk initialization. - void initialize(std::uintptr_t pThunkInitFcn, - pal::dll_t dll, - std::uint32_t token, - std::uintptr_t *pSlot); - - // Returns the slot address of the vtable entry for this thunk - std::uintptr_t *get_slot_address(); - - // Returns the pal::dll_t for this thunk's module - pal::dll_t get_dll_handle(); - - // Returns the token of this thunk - std::uint32_t get_token(); - - std::uintptr_t get_entrypoint(); -}; -#include - -#endif diff --git a/src/tests/build.cmd b/src/tests/build.cmd index 22bc3ea843ee3..7e70fa991dc1a 100644 --- a/src/tests/build.cmd +++ b/src/tests/build.cmd @@ -70,7 +70,6 @@ if /i "%1" == "--" (set processedArgs=!processedArgs! %1&s @REM The following arguments do not support '/', '-', or '--' prefixes if /i "%1" == "x64" (set __BuildArch=x64&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "x86" (set __BuildArch=x86&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) -if /i "%1" == "arm" (set __BuildArch=arm&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "arm64" (set __BuildArch=arm64&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "debug" (set __BuildType=Debug&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) @@ -371,7 +370,7 @@ echo All arguments are optional and case-insensitive, and the '-' prefix is opti echo. echo.-? -h --help: View this message. echo. -echo Build architecture: one of "x64", "x86", "arm", "arm64" ^(default: x64^). +echo Build architecture: one of "x64", "x86", "arm64" ^(default: x64^). echo Build type: one of "Debug", "Checked", "Release" ^(default: Debug^). echo. echo -Rebuild: Clean up all test artifacts prior to building tests. diff --git a/src/tests/issues.targets b/src/tests/issues.targets index bf27e2cb576e8..02dc07ab9a940 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -294,235 +294,6 @@ - - - - https://github.com/dotnet/runtime/issues/49184 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - https://github.com/dotnet/runtime/issues/11360 - - - Native member function calling conventions not supported on Windows ARM32. - - - Native member function calling conventions not supported on Windows ARM32. - - - Native member function calling conventions not supported on Windows ARM32. - - - Native member function calling conventions not supported on Windows ARM32. - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/67870 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - https://github.com/dotnet/runtime/issues/12979 - - - Allocates large contiguous array that is not consistently available on 32-bit platforms - - - https://github.com/dotnet/runtime/issues/60152 - - - https://github.com/dotnet/runtime/issues/66745 - - - https://github.com/dotnet/runtime/issues/66745 - - - https://github.com/dotnet/runtime/issues/84750 - - - https://github.com/dotnet/runtime/issues/84750 - - - https://github.com/dotnet/runtime/issues/81241 - - - diff --git a/src/tests/run.cmd b/src/tests/run.cmd index 0c79426b6c437..bcd49e479e3f0 100644 --- a/src/tests/run.cmd +++ b/src/tests/run.cmd @@ -45,7 +45,6 @@ if /i "%1" == "-help" goto Usage if /i "%1" == "x64" (set __BuildArch=x64&shift&goto Arg_Loop) if /i "%1" == "x86" (set __BuildArch=x86&shift&goto Arg_Loop) -if /i "%1" == "arm" (set __BuildArch=arm&shift&goto Arg_Loop) if /i "%1" == "arm64" (set __BuildArch=arm64&shift&goto Arg_Loop) if /i "%1" == "debug" (set __BuildType=Debug&shift&goto Arg_Loop) @@ -200,7 +199,7 @@ echo. echo where: echo. echo./? -? /h -h /help -help - View this message. -echo ^ - Specifies build architecture: x64, x86, arm, or arm64 ^(default: x64^). +echo ^ - Specifies build architecture: x64, x86, or arm64 ^(default: x64^). echo ^ - Specifies build type: Debug, Release, or Checked ^(default: Debug^). echo TestEnv ^ - Run a custom script before every test to set custom test environment settings. echo sequential - Run tests sequentially ^(no parallelism^).