summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorRahul Kumar <rahku@microsoft.com>2016-06-20 15:33:19 -0700
committerRahul Kumar <rahku@microsoft.com>2016-06-21 12:31:26 -0700
commitce39651fb42e68883a14f498c0bbc39dd5230d88 (patch)
treedb7d82258630158c6253412cf2dd70c107eb1e64 /src/vm
parentb9f5ae88cc49836c8d31f07db7800707165cdb06 (diff)
downloadcoreclr-ce39651fb42e68883a14f498c0bbc39dd5230d88.tar.gz
coreclr-ce39651fb42e68883a14f498c0bbc39dd5230d88.tar.bz2
coreclr-ce39651fb42e68883a14f498c0bbc39dd5230d88.zip
Arm64:return buffer arg should be passed in x8
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/arm64/CallDescrWorkerARM64.asm35
-rw-r--r--src/vm/arm64/asmconstants.h4
-rw-r--r--src/vm/arm64/asmhelpers.asm83
-rw-r--r--src/vm/arm64/asmmacros.h10
-rw-r--r--src/vm/arm64/cgencpu.h10
-rw-r--r--src/vm/arm64/stubs.cpp4
-rw-r--r--src/vm/arm64/virtualcallstubcpu.hpp24
-rw-r--r--src/vm/callingconvention.h23
-rw-r--r--src/vm/comdelegate.cpp14
9 files changed, 119 insertions, 88 deletions
diff --git a/src/vm/arm64/CallDescrWorkerARM64.asm b/src/vm/arm64/CallDescrWorkerARM64.asm
index 7495eb767f..556983934e 100644
--- a/src/vm/arm64/CallDescrWorkerARM64.asm
+++ b/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/vm/arm64/asmconstants.h b/src/vm/arm64/asmconstants.h
index a574cc2716..4edbbfccfd 100644
--- a/src/vm/arm64/asmconstants.h
+++ b/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/vm/arm64/asmhelpers.asm b/src/vm/arm64/asmhelpers.asm
index 88518366ae..72794adef1 100644
--- a/src/vm/arm64/asmhelpers.asm
+++ b/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/vm/arm64/asmmacros.h b/src/vm/arm64/asmmacros.h
index 63714e1019..b24c0fd99a 100644
--- a/src/vm/arm64/asmmacros.h
+++ b/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/vm/arm64/cgencpu.h b/src/vm/arm64/cgencpu.h
index cd54ea08ca..4929cd1dc9 100644
--- a/src/vm/arm64/cgencpu.h
+++ b/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/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp
index 01a56e39fc..a3512a83ec 100644
--- a/src/vm/arm64/stubs.cpp
+++ b/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/vm/arm64/virtualcallstubcpu.hpp b/src/vm/arm64/virtualcallstubcpu.hpp
index b3ee6640ce..b7c52091de 100644
--- a/src/vm/arm64/virtualcallstubcpu.hpp
+++ b/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/vm/callingconvention.h b/src/vm/callingconvention.h
index 74862c04a9..3ef6be983a 100644
--- a/src/vm/callingconvention.h
+++ b/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<ARGITERATOR_BASE>::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<ARGITERATOR_BASE>::GetVASigCookieOffset()
ret += sizeof(void*);
}
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
{
ret += sizeof(void*);
}
@@ -814,7 +819,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetParamTypeArgOffset()
ret += sizeof(void*);
}
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
{
ret += sizeof(void*);
}
@@ -845,7 +850,7 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
if (this->HasThis())
numRegistersUsed++;
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
numRegistersUsed++;
_ASSERTE(!this->IsVarArg() || !this->HasParamType());
@@ -1450,7 +1455,7 @@ void ArgIteratorTemplate<ARGITERATOR_BASE>::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/vm/comdelegate.cpp b/src/vm/comdelegate.cpp
index 071c65be39..c400fc36ab 100644
--- a/src/vm/comdelegate.cpp
+++ b/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