diff options
Diffstat (limited to 'src/vm/amd64/CallDescrWorkerAMD64.asm')
-rw-r--r-- | src/vm/amd64/CallDescrWorkerAMD64.asm | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/vm/amd64/CallDescrWorkerAMD64.asm b/src/vm/amd64/CallDescrWorkerAMD64.asm new file mode 100644 index 0000000000..7607a421f2 --- /dev/null +++ b/src/vm/amd64/CallDescrWorkerAMD64.asm @@ -0,0 +1,132 @@ +; Licensed to the .NET Foundation under one or more agreements. +; The .NET Foundation licenses this file to you under the MIT license. +; See the LICENSE file in the project root for more information. + +include <AsmMacros.inc> +include <AsmConstants.inc> + +extern CallDescrWorkerUnwindFrameChainHandler:proc + +;; +;; EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr); +;; + NESTED_ENTRY FastCallFinalizeWorker, _TEXT, CallDescrWorkerUnwindFrameChainHandler + alloc_stack 28h ;; alloc callee scratch and align the stack + END_PROLOGUE + + ; + ; RCX: already contains obj* + ; RDX: address of finalizer method to call + ; + + ; !!!!!!!!! + ; NOTE: you cannot tail call here because we must have the CallDescrWorkerUnwindFrameChainHandler + ; personality routine on the stack. + ; !!!!!!!!! + call rdx + xor rax, rax + + ; epilog + add rsp, 28h + ret + + + NESTED_END FastCallFinalizeWorker, _TEXT + +;;extern "C" void CallDescrWorkerInternal(CallDescrData * pCallDescrData); + + NESTED_ENTRY CallDescrWorkerInternal, _TEXT, CallDescrWorkerUnwindFrameChainHandler + + push_nonvol_reg rbx ; save nonvolatile registers + push_nonvol_reg rsi ; + push_nonvol_reg rbp ; + set_frame rbp, 0 ; set frame pointer + + END_PROLOGUE + + mov rbx, rcx ; save pCallDescrData in rbx + + mov ecx, dword ptr [rbx + CallDescrData__numStackSlots] + + test ecx, 1 + jz StackAligned + push rax +StackAligned: + + mov rsi, [rbx + CallDescrData__pSrc] ; set source argument list address + lea rsi, [rsi + 8 * rcx] + +StackCopyLoop: ; copy the arguments to stack top-down to carefully probe for sufficient stack space + sub rsi, 8 + push qword ptr [rsi] + dec ecx + jnz StackCopyLoop + + ; + ; N.B. All four argument registers are loaded regardless of the actual number + ; of arguments. + ; + + mov rax, [rbx + CallDescrData__dwRegTypeMap] ; save the reg (arg) type map + + mov rcx, 0[rsp] ; load first four argument registers + movss xmm0, real4 ptr 0[rsp] ; + cmp al, ASM_ELEMENT_TYPE_R8 ; + jnz Arg2 ; + movsd xmm0, real8 ptr 0[rsp] ; +Arg2: + mov rdx, 8[rsp] ; + movss xmm1, real4 ptr 8[rsp] ; + cmp ah, ASM_ELEMENT_TYPE_R8 ; + jnz Arg3 ; + movsd xmm1, real8 ptr 8[rsp] ; +Arg3: + mov r8, 10h[rsp] ; + movss xmm2, real4 ptr 10h[rsp]; + shr eax, 16 ; + cmp al, ASM_ELEMENT_TYPE_R8 ; + jnz Arg4 ; + movsd xmm2, real8 ptr 10h[rsp]; +Arg4: + mov r9, 18h[rsp] ; + movss xmm3, real4 ptr 18h[rsp]; + cmp ah, ASM_ELEMENT_TYPE_R8 ; + jnz DoCall ; + movsd xmm3, real8 ptr 18h[rsp]; +DoCall: + call qword ptr [rbx+CallDescrData__pTarget] ; call target function + + ; Save FP return value + + mov ecx, dword ptr [rbx+CallDescrData__fpReturnSize] + test ecx, ecx + jz ReturnsInt + + cmp ecx, 4 + je ReturnsFloat + cmp ecx, 8 + je ReturnsDouble + ; unexpected + jmp Epilog + +ReturnsInt: + mov [rbx+CallDescrData__returnValue], rax + +Epilog: + lea rsp, 0[rbp] ; deallocate argument list + pop rbp ; restore nonvolatile register + pop rsi ; + pop rbx ; + ret + +ReturnsFloat: + movss real4 ptr [rbx+CallDescrData__returnValue], xmm0 + jmp Epilog + +ReturnsDouble: + movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0 + jmp Epilog + + NESTED_END CallDescrWorkerInternal, _TEXT + + end |