From: Rahul Kumar Date: Mon, 20 Jun 2016 22:33:19 +0000 (-0700) Subject: Arm64:return buffer arg should be passed in x8 X-Git-Tag: submit/tizen/20210909.063632~11030^2~10055^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cbee10c47a89f57156375ada0c2adc0b55b3c6de;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Arm64:return buffer arg should be passed in x8 Commit migrated from https://github.com/dotnet/coreclr/commit/ce39651fb42e68883a14f498c0bbc39dd5230d88 --- diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h index c0f53fc..49ebc4b 100644 --- a/src/coreclr/src/jit/target.h +++ b/src/coreclr/src/jit/target.h @@ -1897,8 +1897,7 @@ inline bool genIsValidDoubleReg(regNumber reg) // inline bool hasFixedRetBuffReg() { - // Disable this until the VM changes are also enabled -#if 0 //def _TARGET_ARM64_ +#ifdef _TARGET_ARM64_ return true; #else return false; diff --git a/src/coreclr/src/vm/arm64/CallDescrWorkerARM64.asm b/src/coreclr/src/vm/arm64/CallDescrWorkerARM64.asm index 7495eb7..5569839 100644 --- a/src/coreclr/src/vm/arm64/CallDescrWorkerARM64.asm +++ b/src/coreclr/src/vm/arm64/CallDescrWorkerARM64.asm @@ -52,29 +52,30 @@ Lstackloop bne Lstackloop Ldonestack - ;; If FP arguments are supplied in registers (x8 != NULL) then initialize all of them from the pointer - ;; given in x8. - ldr x8, [x19,#CallDescrData__pFloatArgumentRegisters] - cbz x8, LNoFloatingPoint - ldp d0, d1, [x8] - ldp d2, d3, [x8, #16] - ldp d4, d5, [x8, #32] - ldp d6, d7, [x8, #48] + ;; If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer + ;; given in x9. + ldr x9, [x19,#CallDescrData__pFloatArgumentRegisters] + cbz x9, LNoFloatingPoint + ldp d0, d1, [x9] + ldp d2, d3, [x9, #16] + ldp d4, d5, [x9, #32] + ldp d6, d7, [x9, #48] LNoFloatingPoint - ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 56] - ;; into x0, ..., x7 + ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 64] + ;; into x0, ..., x7, x8 - ldr x8, [x19,#CallDescrData__pArgumentRegisters] - ldp x0, x1, [x8] - ldp x2, x3, [x8, #16] - ldp x4, x5, [x8, #32] - ldp x6, x7, [x8, #48] + ldr x9, [x19,#CallDescrData__pArgumentRegisters] + ldp x0, x1, [x9] + ldp x2, x3, [x9, #16] + ldp x4, x5, [x9, #32] + ldp x6, x7, [x9, #48] + ldr x8, [x9, #64] ;; ARM64TODO: => see if anything special needs to be done for remoting ;; call pTarget - ldr x8, [x19,#CallDescrData__pTarget] - blr x8 + ldr x9, [x19,#CallDescrData__pTarget] + blr x9 ldr w3, [x19,#CallDescrData__fpReturnSize] diff --git a/src/coreclr/src/vm/arm64/asmconstants.h b/src/coreclr/src/vm/arm64/asmconstants.h index a574cc2..4edbbfc 100644 --- a/src/coreclr/src/vm/arm64/asmconstants.h +++ b/src/coreclr/src/vm/arm64/asmconstants.h @@ -48,7 +48,7 @@ ASMCONSTANTS_C_ASSERT(AppDomain__m_dwId == offsetof(AppDomain, m_dwId)); #define METHODDESC_REGISTER x12 -#define SIZEOF__ArgumentRegisters 0x40 +#define SIZEOF__ArgumentRegisters 0x48 ASMCONSTANTS_C_ASSERT(SIZEOF__ArgumentRegisters == sizeof(ArgumentRegisters)) #define SIZEOF__FloatArgumentRegisters 0x40 @@ -116,7 +116,7 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__CONTEXT == sizeof(T_CONTEXT)); #ifdef FEATURE_COMINTEROP -#define SIZEOF__ComMethodFrame 0x68 +#define SIZEOF__ComMethodFrame 0x70 ASMCONSTANTS_C_ASSERT(SIZEOF__ComMethodFrame == sizeof(ComMethodFrame)); #define UnmanagedToManagedFrame__m_pvDatum 0x10 diff --git a/src/coreclr/src/vm/arm64/asmhelpers.asm b/src/coreclr/src/vm/arm64/asmhelpers.asm index 8851836..72794ad 100644 --- a/src/coreclr/src/vm/arm64/asmhelpers.asm +++ b/src/coreclr/src/vm/arm64/asmhelpers.asm @@ -167,18 +167,18 @@ Done ; The call in ndirect import precode points to this function. NESTED_ENTRY NDirectImportThunk - PROLOG_SAVE_REG_PAIR fp, lr, #-144! + PROLOG_SAVE_REG_PAIR fp, lr, #-160! SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 mov x0, x12 bl NDirectImportWorker mov x12, x0 ; pop the stack and restore original register state - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 RESTORE_ARGUMENT_REGISTERS sp, 16 - EPILOG_RESTORE_REG_PAIR fp, lr, #144! + EPILOG_RESTORE_REG_PAIR fp, lr, #160! ; If we got back from NDirectImportWorker, the MD has been successfully ; linked. Proceed to execute the original DLL call. @@ -367,9 +367,9 @@ Exit NESTED_ENTRY VirtualMethodFixupStub ; Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-144! + PROLOG_SAVE_REG_PAIR fp, lr, #-160! SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 ; Refer to ZapImportVirtualThunk::Save ; for details on this. @@ -386,8 +386,8 @@ Exit ; pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 - EPILOG_RESTORE_REG_PAIR fp, lr, #144! + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 + EPILOG_RESTORE_REG_PAIR fp, lr, #160! PATCH_LABEL VirtualMethodFixupPatchLabel @@ -462,20 +462,25 @@ LNullThis GBLA ComCallPreStub_StackAlloc GBLA ComCallPreStub_FrameOffset GBLA ComCallPreStub_ErrorReturnOffset + GBLA ComCallPreStub_FirstStackAdjust ComCallPreStub_FrameSize SETA (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) -ComCallPreStub_StackAlloc SETA ComCallPreStub_FrameSize - SIZEOF__ArgumentRegisters - 2 * 8 ; reg args , fp & lr already pushed +ComCallPreStub_FirstStackAdjust SETA (SIZEOF__ArgumentRegisters + 2 * 8) ; reg args , fp & lr already pushed +ComCallPreStub_StackAlloc SETA ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust ComCallPreStub_StackAlloc SETA ComCallPreStub_StackAlloc + SIZEOF__FloatArgumentRegisters + 8; 8 for ErrorReturn - IF ComCallPreStub_StackAlloc:MOD:16 != 0 ComCallPreStub_StackAlloc SETA ComCallPreStub_StackAlloc + 8 ENDIF -ComCallPreStub_FrameOffset SETA (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters - 2 * 8)) +ComCallPreStub_FrameOffset SETA (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - ComCallPreStub_FirstStackAdjust)) ComCallPreStub_ErrorReturnOffset SETA SIZEOF__FloatArgumentRegisters + IF (ComCallPreStub_FirstStackAdjust):MOD:16 != 0 +ComCallPreStub_FirstStackAdjust SETA ComCallPreStub_FirstStackAdjust + 8 + ENDIF + ; Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-80! + PROLOG_SAVE_REG_PAIR fp, lr, #-ComCallPreStub_FirstStackAdjust! PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) @@ -496,7 +501,7 @@ ComCallPreStub_ErrorReturnOffset SETA SIZEOF__FloatArgumentRegisters RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, #80! + EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust! ; and tailcall to the actual method EPILOG_BRANCH_REG x12 @@ -506,7 +511,7 @@ ComCallPreStub_ErrorExit ; pop the stack EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, #80! + EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust! EPILOG_RETURN @@ -527,19 +532,26 @@ ComCallPreStub_ErrorExit GBLA GenericComCallStub_FrameSize GBLA GenericComCallStub_StackAlloc GBLA GenericComCallStub_FrameOffset + GBLA GenericComCallStub_FirstStackAdjust GenericComCallStub_FrameSize SETA (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) -GenericComCallStub_StackAlloc SETA GenericComCallStub_FrameSize - SIZEOF__ArgumentRegisters - 2 * 8 +GenericComCallStub_FirstStackAdjust SETA (SIZEOF__ArgumentRegisters + 2 * 8) +GenericComCallStub_StackAlloc SETA GenericComCallStub_FrameSize - GenericComCallStub_FirstStackAdjust GenericComCallStub_StackAlloc SETA GenericComCallStub_StackAlloc + SIZEOF__FloatArgumentRegisters - IF GenericComCallStub_StackAlloc:MOD:16 != 0 + IF (GenericComCallStub_StackAlloc):MOD:16 != 0 GenericComCallStub_StackAlloc SETA GenericComCallStub_StackAlloc + 8 ENDIF -GenericComCallStub_FrameOffset SETA (GenericComCallStub_StackAlloc - (SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters - 2 * 8)) +GenericComCallStub_FrameOffset SETA (GenericComCallStub_StackAlloc - (SIZEOF__ComMethodFrame - GenericComCallStub_FirstStackAdjust)) + + IF (GenericComCallStub_FirstStackAdjust):MOD:16 != 0 +GenericComCallStub_FirstStackAdjust SETA GenericComCallStub_FirstStackAdjust + 8 + ENDIF + ; Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-80! + PROLOG_SAVE_REG_PAIR fp, lr, #-GenericComCallStub_FirstStackAdjust! PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc) @@ -551,7 +563,7 @@ GenericComCallStub_FrameOffset SETA (GenericComCallStub_StackAlloc - (SIZE ; pop the stack EPILOG_STACK_FREE GenericComCallStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, #80! + EPILOG_RESTORE_REG_PAIR fp, lr, #GenericComCallStub_FirstStackAdjust! EPILOG_RETURN @@ -596,6 +608,7 @@ COMToCLRDispatchHelper_RegSetup ldp x2, x3, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 16)] ldp x4, x5, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 32)] ldp x6, x7, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 48)] + ldr x8, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 64)] ldr x1, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 8)] @@ -615,9 +628,9 @@ COMToCLRDispatchHelper_RegSetup NESTED_ENTRY TheUMEntryPrestub,,UMEntryPrestubUnwindFrameChainHandler ; Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-144! + PROLOG_SAVE_REG_PAIR fp, lr, #-160! SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 mov x0, x12 bl TheUMEntryPrestubWorker @@ -627,8 +640,8 @@ COMToCLRDispatchHelper_RegSetup ; pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 - EPILOG_RESTORE_REG_PAIR fp, lr, #144! + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 + EPILOG_RESTORE_REG_PAIR fp, lr, #160! ; and tailcall to the actual method EPILOG_BRANCH_REG x12 @@ -641,16 +654,16 @@ COMToCLRDispatchHelper_RegSetup NESTED_ENTRY UMThunkStub,,UMThunkStubUnwindFrameChainHandler ; Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-96! ; 64 for regArgs, 8 for x19 & 8 for x12 + PROLOG_SAVE_REG_PAIR fp, lr, #-112! ; 72 for regArgs, 8 for x19 & 8 for x12 & 8 for 16-byte align ; save callee saved reg x19. x19 is used in the method to store thread* - PROLOG_SAVE_REG x19, #88 + PROLOG_SAVE_REG x19, #96 SAVE_ARGUMENT_REGISTERS sp, 16 GBLA UMThunkStub_HiddenArg ; offset of saved UMEntryThunk * GBLA UMThunkStub_StackArgs ; offset of original stack args (total size of UMThunkStub frame) -UMThunkStub_HiddenArg SETA 80 -UMThunkStub_StackArgs SETA 96 +UMThunkStub_HiddenArg SETA 88 +UMThunkStub_StackArgs SETA 112 ; save UMEntryThunk* str x12, [sp, #UMThunkStub_HiddenArg] @@ -728,8 +741,8 @@ UMThunkStub_PostCall str w4, [x19, #Thread__m_fPreemptiveGCDisabled] EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #88 - EPILOG_RESTORE_REG_PAIR fp, lr, #96! + EPILOG_RESTORE_REG x19, #96 + EPILOG_RESTORE_REG_PAIR fp, lr, #112! EPILOG_RETURN @@ -1157,7 +1170,7 @@ Fail NESTED_END ResolveWorkerChainLookupAsmStub ;; ------------------------------------------------------------------ -;; void ResolveWorkerAsmStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken) +;; void ResolveWorkerAsmStub(args in regs x0-x7 & stack and possibly retbuf arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken) ;; ;; The stub dispatch thunk which transfers control to VSD_ResolveWorker. NESTED_ENTRY ResolveWorkerAsmStub @@ -1184,8 +1197,8 @@ Fail add x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock mov x1, x11 ; Indirection cell - mov x2, x8 ; sectionIndex - mov x3, x9 ; Module* + mov x2, x9 ; sectionIndex + mov x3, x10 ; Module* bl ExternalMethodFixupWorker mov x12, x0 @@ -1203,8 +1216,8 @@ Fail add x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock mov x1, x11 ; Indirection cell - mov x2, x8 ; sectionIndex - mov x3, x9 ; Module* + mov x2, x9 ; sectionIndex + mov x3, x10 ; Module* mov x4, $frameFlags bl DynamicHelperWorker cbnz x0, %FT0 @@ -1224,7 +1237,7 @@ Fail #ifdef FEATURE_PREJIT ;; ------------------------------------------------------------------ -;; void StubDispatchFixupStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken) +;; void StubDispatchFixupStub(args in regs x0-x7 & stack and possibly retbuff arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken) ;; ;; The stub dispatch thunk which transfers control to StubDispatchFixupWorker. NESTED_ENTRY StubDispatchFixupStub diff --git a/src/coreclr/src/vm/arm64/asmmacros.h b/src/coreclr/src/vm/arm64/asmmacros.h index 63714e1..b24c0fd 100644 --- a/src/coreclr/src/vm/arm64/asmmacros.h +++ b/src/coreclr/src/vm/arm64/asmmacros.h @@ -65,7 +65,7 @@ __PWTB_TransitionBlock SETA __PWTB_FloatArgumentRegisters __PWTB_StackAlloc SETA __PWTB_TransitionBlock __PWTB_ArgumentRegisters SETA __PWTB_StackAlloc + 96 - PROLOG_SAVE_REG_PAIR fp, lr, #-160! + PROLOG_SAVE_REG_PAIR fp, lr, #-176! ; Spill callee saved registers PROLOG_SAVE_REG_PAIR x19, x20, #16 PROLOG_SAVE_REG_PAIR x21, x22, #32 @@ -98,7 +98,7 @@ __PWTB_ArgumentRegisters SETA __PWTB_StackAlloc + 96 EPILOG_RESTORE_REG_PAIR x23, x24, #48 EPILOG_RESTORE_REG_PAIR x25, x26, #64 EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR fp, lr, #160! + EPILOG_RESTORE_REG_PAIR fp, lr, #176! EPILOG_RETURN MEND @@ -121,7 +121,7 @@ __PWTB_ArgumentRegisters SETA __PWTB_StackAlloc + 96 EPILOG_RESTORE_REG_PAIR x23, x24, #48 EPILOG_RESTORE_REG_PAIR x25, x26, #64 EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR fp, lr, #160! + EPILOG_RESTORE_REG_PAIR fp, lr, #176! MEND ;----------------------------------------------------------------------------- @@ -151,7 +151,7 @@ $FuncName ; base address to be passed in $reg ; -; Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS +; Reserve 72 bytes of memory before calling SAVE_ARGUMENT_REGISTERS MACRO SAVE_ARGUMENT_REGISTERS $reg, $offset @@ -167,6 +167,7 @@ __PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET SETA 0 stp x2, x3, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 16)] stp x4, x5, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 32)] stp x6, x7, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 48)] + str x8, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 64)] MEND ; Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS @@ -202,6 +203,7 @@ __PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET SETA 0 ldp x2, x3, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 16)] ldp x4, x5, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 32)] ldp x6, x7, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 48)] + ldr x8, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 64)] MEND MACRO diff --git a/src/coreclr/src/vm/arm64/cgencpu.h b/src/coreclr/src/vm/arm64/cgencpu.h index cd54ea0..4929cd1 100644 --- a/src/coreclr/src/vm/arm64/cgencpu.h +++ b/src/coreclr/src/vm/arm64/cgencpu.h @@ -109,9 +109,9 @@ struct CalleeSavedRegisters { //-------------------------------------------------------------------- typedef DPTR(struct ArgumentRegisters) PTR_ArgumentRegisters; struct ArgumentRegisters { - INT64 x[8]; // x0 ....x7 + INT64 x[9]; // x0 ....x7 & x8 can contain return buffer address }; -#define NUM_ARGUMENT_REGISTERS 8 +#define NUM_ARGUMENT_REGISTERS 9 #define ARGUMENTREGISTERS_SIZE sizeof(ArgumentRegisters) @@ -519,10 +519,10 @@ typedef DPTR(StubPrecode) PTR_StubPrecode; struct NDirectImportPrecode { - static const int Type = 0x88; + static const int Type = 0x8B; - // adr x8, #16 ; Notice that x8 register is used to differentiate the stub from StubPrecode which uses x9 - // ldp x10,x12,[x8] ; =m_pTarget,m_pMethodDesc + // adr x11, #16 ; Notice that x11 register is used to differentiate the stub from StubPrecode which uses x9 + // ldp x10,x12,[x11] ; =m_pTarget,m_pMethodDesc // br x10 // 4 byte padding for 8 byte allignement // dcd pTarget diff --git a/src/coreclr/src/vm/arm64/stubs.cpp b/src/coreclr/src/vm/arm64/stubs.cpp index 01a56e3..a3512a8 100644 --- a/src/coreclr/src/vm/arm64/stubs.cpp +++ b/src/coreclr/src/vm/arm64/stubs.cpp @@ -532,8 +532,8 @@ void NDirectImportPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocat int n = 0; - m_rgCode[n++] = 0x10000088; // adr x8, #16 - m_rgCode[n++] = 0xA940310A; // ldp x10,x12,[x8] + m_rgCode[n++] = 0x1000008B; // adr x11, #16 + m_rgCode[n++] = 0xA940316A; // ldp x10,x12,[x11] m_rgCode[n++] = 0xD61F0140; // br x10 _ASSERTE(n+1 == _countof(m_rgCode)); diff --git a/src/coreclr/src/vm/arm64/virtualcallstubcpu.hpp b/src/coreclr/src/vm/arm64/virtualcallstubcpu.hpp index b3ee664..b7c5209 100644 --- a/src/coreclr/src/vm/arm64/virtualcallstubcpu.hpp +++ b/src/coreclr/src/vm/arm64/virtualcallstubcpu.hpp @@ -7,7 +7,7 @@ #ifndef _VIRTUAL_CALL_STUB_ARM_H #define _VIRTUAL_CALL_STUB_ARM_H -#define DISPATCH_STUB_FIRST_DWORD 0xf9400008 +#define DISPATCH_STUB_FIRST_DWORD 0xf940000d #define RESOLVE_STUB_FIRST_DWORD 0xF940000C struct ARM64EncodeHelpers @@ -92,10 +92,10 @@ struct DispatchHolder void Initialize(PCODE implTarget, PCODE failTarget, size_t expectedMT) { - // ldr x8, [x0] ; methodTable from object in x0 + // ldr x13, [x0] ; methodTable from object in x0 // adr x9, _expectedMT ; _expectedMT is at offset 28 from pc // ldp x10, x12, [x9] ; x10 = _expectedMT & x12 = _implTarget - // cmp x8, x10 + // cmp x13, x10 // bne failLabel // br x12 // failLabel @@ -105,10 +105,10 @@ struct DispatchHolder // _implTarget // _failTarget - _stub._entryPoint[0] = DISPATCH_STUB_FIRST_DWORD; // 0xf9400008 + _stub._entryPoint[0] = DISPATCH_STUB_FIRST_DWORD; // 0xf940000d _stub._entryPoint[1] = 0x100000e9; _stub._entryPoint[2] = 0xa940312a; - _stub._entryPoint[3] = 0xeb0a011f; + _stub._entryPoint[3] = 0xeb0a01bf; _stub._entryPoint[4] = 0x54000041; _stub._entryPoint[5] = 0xd61f0180; _stub._entryPoint[6] = 0x580000c9; @@ -189,12 +189,12 @@ struct ResolveHolder // x9 = e = this._cacheAddress + i // if (mt == e.pMT && this._token == e.token) // { - // (e.target)(x0, [x1,...,x7]); + // (e.target)(x0, [x1,...,x7 and x8]); // } // else // { // x12 = this._token; - // (this._slowEntryPoint)(x0, [x1,.., x7], x9, x11, x12); + // (this._slowEntryPoint)(x0, [x1,.., x7 and x8], x9, x11, x12); // } // } // @@ -293,10 +293,10 @@ struct ResolveHolder _ASSERTE(n == ResolveStub::resolveEntryPointLen); _ASSERTE(_stub._resolveEntryPoint + n == _stub._slowEntryPoint); - // ResolveStub._slowEntryPoint(x0:MethodToken, [x1..x7], x11:IndirectionCellAndFlags) + // ResolveStub._slowEntryPoint(x0:MethodToken, [x1..x7 and x8], x11:IndirectionCellAndFlags) // { // x12 = this._token; - // this._resolveWorkerTarget(x0, [x1..x7], x9, x11, x12); + // this._resolveWorkerTarget(x0, [x1..x7 and x8], x9, x11, x12); // } #undef PC_REL_OFFSET @@ -323,10 +323,10 @@ struct ResolveHolder _stub._slowEntryPoint[n++] = 0xD61F01A0; _ASSERTE(n == ResolveStub::slowEntryPointLen); - // ResolveStub._failEntryPoint(x0:MethodToken, x1,.., x7, x11:IndirectionCellAndFlags) + // ResolveStub._failEntryPoint(x0:MethodToken, x1,.., x7 and x8, x11:IndirectionCellAndFlags) // { // if(--*(this._pCounter) < 0) x11 = x11 | SDF_ResolveBackPatch; - // this._resolveEntryPoint(x0, [x1..x7]); + // this._resolveEntryPoint(x0, [x1..x7 and x8]); // } #undef PC_REL_OFFSET //NOTE Offset can be negative @@ -428,7 +428,7 @@ VirtualCallStubManager::StubKind VirtualCallStubManager::predictStubKind(PCODE s DWORD firstDword = *((DWORD*) pInstr); - if (firstDword == DISPATCH_STUB_FIRST_DWORD) // assembly of first instruction of DispatchStub : ldr x8, [x0] + if (firstDword == DISPATCH_STUB_FIRST_DWORD) // assembly of first instruction of DispatchStub : ldr x13, [x0] { stubKind = SK_DISPATCH; } diff --git a/src/coreclr/src/vm/callingconvention.h b/src/coreclr/src/vm/callingconvention.h index 74862c0..3ef6be9 100644 --- a/src/coreclr/src/vm/callingconvention.h +++ b/src/coreclr/src/vm/callingconvention.h @@ -13,6 +13,8 @@ #ifndef __CALLING_CONVENTION_INCLUDED #define __CALLING_CONVENTION_INCLUDED +BOOL IsRetBuffPassedAsFirstArg(); + // Describes how a single argument is laid out in registers and/or stack locations when given as an input to a // managed method as part of a larger signature. // @@ -111,6 +113,7 @@ struct TransitionBlock }; }; ArgumentRegisters m_argumentRegisters; + TADDR padding; // Keep size of TransitionBlock as multiple of 16-byte. Simplifies code in PROLOG_WITH_TRANSITION_BLOCK #else PORTABILITY_ASSERT("TransitionBlock"); #endif @@ -734,6 +737,8 @@ int ArgIteratorTemplate::GetRetBuffArgOffset() #if _TARGET_X86_ // x86 is special as always ret += this->HasThis() ? offsetof(ArgumentRegisters, EDX) : offsetof(ArgumentRegisters, ECX); +#elif _TARGET_ARM64_ + ret += (int) offsetof(ArgumentRegisters, x[8]); #else if (this->HasThis()) ret += sizeof(void *); @@ -761,7 +766,7 @@ int ArgIteratorTemplate::GetVASigCookieOffset() ret += sizeof(void*); } - if (this->HasRetBuffArg()) + if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) { ret += sizeof(void*); } @@ -814,7 +819,7 @@ int ArgIteratorTemplate::GetParamTypeArgOffset() ret += sizeof(void*); } - if (this->HasRetBuffArg()) + if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) { ret += sizeof(void*); } @@ -845,7 +850,7 @@ int ArgIteratorTemplate::GetNextOffset() if (this->HasThis()) numRegistersUsed++; - if (this->HasRetBuffArg()) + if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) numRegistersUsed++; _ASSERTE(!this->IsVarArg() || !this->HasParamType()); @@ -1450,7 +1455,7 @@ void ArgIteratorTemplate::ForceSigWalk() if (this->HasThis()) numRegistersUsed++; - if (this->HasRetBuffArg()) + if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) numRegistersUsed++; if (this->IsVarArg()) @@ -1692,4 +1697,14 @@ inline BOOL HasRetBuffArg(MetaSig * pSig) return argit.HasRetBuffArg(); } +inline BOOL IsRetBuffPassedAsFirstArg() +{ + WRAPPER_NO_CONTRACT; +#ifndef _TARGET_ARM64_ + return TRUE; +#else + return FALSE; +#endif +} + #endif // __CALLING_CONVENTION_INCLUDED diff --git a/src/coreclr/src/vm/comdelegate.cpp b/src/coreclr/src/vm/comdelegate.cpp index 071c65b..c400fc3 100644 --- a/src/coreclr/src/vm/comdelegate.cpp +++ b/src/coreclr/src/vm/comdelegate.cpp @@ -611,7 +611,7 @@ Stub* COMDelegate::SetupShuffleThunk(MethodTable * pDelMT, MethodDesc *pTargetMe EnsureWritablePages(pClass); - if (!pTargetMeth->IsStatic() && pTargetMeth->HasRetBuffArg()) + if (!pTargetMeth->IsStatic() && pTargetMeth->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) { if (FastInterlockCompareExchangePointer(&pClass->m_pInstRetBuffCallStub, pShuffleThunk, NULL ) != NULL) { @@ -1009,7 +1009,7 @@ void COMDelegate::BindToMethod(DELEGATEREF *pRefThis, // Look for a thunk cached on the delegate class first. Note we need a different thunk for instance methods with a // hidden return buffer argument because the extra argument switches place with the target when coming from the caller. - if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg()) + if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) pShuffleThunk = pDelegateClass->m_pInstRetBuffCallStub; else pShuffleThunk = pDelegateClass->m_pStaticCallStub; @@ -1079,7 +1079,7 @@ void COMDelegate::BindToMethod(DELEGATEREF *pRefThis, pTargetCode = pTargetMethod->GetMultiCallableAddrOfVirtualizedCode(pRefFirstArg, pTargetMethod->GetMethodTable()); else #ifdef HAS_THISPTR_RETBUF_PRECODE - if (pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg()) + if (pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) pTargetCode = pTargetMethod->GetLoaderAllocatorForCode()->GetFuncPtrStubs()->GetFuncPtrStub(pTargetMethod, PRECODE_THISPTR_RETBUF); else #endif // HAS_THISPTR_RETBUF_PRECODE @@ -2044,7 +2044,7 @@ FCIMPL3(void, COMDelegate::DelegateConstruct, Object* refThisUNSAFE, Object* tar // set the shuffle thunk Stub *pShuffleThunk = NULL; - if (!pMeth->IsStatic() && pMeth->HasRetBuffArg()) + if (!pMeth->IsStatic() && pMeth->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) pShuffleThunk = pDelCls->m_pInstRetBuffCallStub; else pShuffleThunk = pDelCls->m_pStaticCallStub; @@ -2162,7 +2162,7 @@ FCIMPL3(void, COMDelegate::DelegateConstruct, Object* refThisUNSAFE, Object* tar } } #ifdef HAS_THISPTR_RETBUF_PRECODE - else if (pMeth->HasRetBuffArg()) + else if (pMeth->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) method = pMeth->GetLoaderAllocatorForCode()->GetFuncPtrStubs()->GetFuncPtrStub(pMeth, PRECODE_THISPTR_RETBUF); #endif // HAS_THISPTR_RETBUF_PRECODE @@ -3569,7 +3569,7 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT pRealCtor = MscorlibBinder::GetMethod(METHOD__MULTICAST_DELEGATE__CTOR_OPENED); } Stub *pShuffleThunk = NULL; - if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg()) + if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) pShuffleThunk = pDelCls->m_pInstRetBuffCallStub; else pShuffleThunk = pDelCls->m_pStaticCallStub; @@ -3597,7 +3597,7 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT #ifdef HAS_THISPTR_RETBUF_PRECODE // Force closed delegates over static methods with return buffer to go via // the slow path to create ThisPtrRetBufPrecode - if (isStatic && pTargetMethod->HasRetBuffArg()) + if (isStatic && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) return NULL; #endif diff --git a/src/coreclr/src/zap/zapimport.cpp b/src/coreclr/src/zap/zapimport.cpp index c1f8693..1412adc 100644 --- a/src/coreclr/src/zap/zapimport.cpp +++ b/src/coreclr/src/zap/zapimport.cpp @@ -2161,19 +2161,19 @@ DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter) // x11 contains indirection cell // Do nothing x11 contains our first param - // movz x8, #index + // movz x9, #index DWORD index = GetSectionIndex(); _ASSERTE(index <= 0x7F); - *(DWORD*)p = 0xd2800008 | (index << 5); + *(DWORD*)p = 0xd2800009 | (index << 5); p += 4; - // move Module* -> x9 - // ldr x9, [PC+0x14] - *(DWORD*)p = 0x580000A9; + // move Module* -> x10 + // ldr x10, [PC+0x14] + *(DWORD*)p = 0x580000AA; p += 4; - //ldr x9, [x9] - *(DWORD*)p = 0xf9400129; + //ldr x10, [x10] + *(DWORD*)p = 0xf940014A; p += 4; } else