Arm64:return buffer arg should be passed in x8
authorRahul Kumar <rahku@microsoft.com>
Mon, 20 Jun 2016 22:33:19 +0000 (15:33 -0700)
committerRahul Kumar <rahku@microsoft.com>
Tue, 21 Jun 2016 19:31:26 +0000 (12:31 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/ce39651fb42e68883a14f498c0bbc39dd5230d88

src/coreclr/src/jit/target.h
src/coreclr/src/vm/arm64/CallDescrWorkerARM64.asm
src/coreclr/src/vm/arm64/asmconstants.h
src/coreclr/src/vm/arm64/asmhelpers.asm
src/coreclr/src/vm/arm64/asmmacros.h
src/coreclr/src/vm/arm64/cgencpu.h
src/coreclr/src/vm/arm64/stubs.cpp
src/coreclr/src/vm/arm64/virtualcallstubcpu.hpp
src/coreclr/src/vm/callingconvention.h
src/coreclr/src/vm/comdelegate.cpp
src/coreclr/src/zap/zapimport.cpp

index c0f53fc..49ebc4b 100644 (file)
@@ -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;
index 7495eb7..5569839 100644 (file)
@@ -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]
 
index a574cc2..4edbbfc 100644 (file)
@@ -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
index 8851836..72794ad 100644 (file)
@@ -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, 8
+    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
index 63714e1..b24c0fd 100644 (file)
@@ -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
index cd54ea0..4929cd1 100644 (file)
@@ -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
index 01a56e3..a3512a8 100644 (file)
@@ -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));
index b3ee664..b7c5209 100644 (file)
@@ -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;
         }
index 74862c0..3ef6be9 100644 (file)
@@ -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
index 071c65b..c400fc3 100644 (file)
@@ -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
 
index c1f8693..1412adc 100644 (file)
@@ -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