diff options
Diffstat (limited to 'src/vm/amd64/calldescrworkeramd64.S')
-rw-r--r-- | src/vm/amd64/calldescrworkeramd64.S | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/vm/amd64/calldescrworkeramd64.S b/src/vm/amd64/calldescrworkeramd64.S new file mode 100644 index 0000000000..05dd8ac8ef --- /dev/null +++ b/src/vm/amd64/calldescrworkeramd64.S @@ -0,0 +1,165 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +#define real4 dword +#define real8 qword + +//extern CallDescrWorkerUnwindFrameChainHandler:proc + +// +// EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr); +// +NESTED_ENTRY FastCallFinalizeWorker, _TEXT, NoHandler + push_nonvol_reg rbp + mov rbp, rsp + END_PROLOGUE + + // + // RDI: already contains obj* + // RSI: address of finalizer method to call + // + + // !!!!!!!!! + // NOTE: you cannot tail call here because we must have the CallDescrWorkerUnwindFrameChainHandler + // personality routine on the stack. + // !!!!!!!!! + call rsi + xor rax, rax + + // epilog + pop_nonvol_reg rbp + ret + + +NESTED_END FastCallFinalizeWorker, _TEXT + +//extern "C" void CallDescrWorkerInternal(CallDescrData * pCallDescrData); + +NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler + push_nonvol_reg rbp + mov rbp, rsp + push_nonvol_reg rbx + alloc_stack 8 // ensure proper alignment of the rsp + set_cfa_register rbp, (2*8) + END_PROLOGUE + + mov rbx, rdi // save pCallDescrData in rbx + + mov ecx, dword ptr [rbx + CallDescrData__numStackSlots] + + and ecx, ecx + jz LOCAL_LABEL(NoStackArguments) + + test ecx, 1 + jz LOCAL_LABEL(StackAligned) + push rax +LOCAL_LABEL(StackAligned): + + mov rsi, [rbx + CallDescrData__pSrc] // set source argument list address + lea rsi, [rsi + 8 * rcx] + +LOCAL_LABEL(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 LOCAL_LABEL(StackCopyLoop) +LOCAL_LABEL(NoStackArguments): + // All argument registers are loaded regardless of the actual number + // of arguments. + + mov rax, [rbx + CallDescrData__pArgumentRegisters] + mov rdi, [rax + 0] + mov rsi, [rax + 8] + mov rdx, [rax + 16] + mov rcx, [rax + 24] + mov r8, [rax + 32] + mov r9, [rax + 40] + + // All float argument registers are loaded regardless of the actual number + // of arguments. + + mov rax, [rbx + CallDescrData__pFloatArgumentRegisters] + and rax, rax + jz LOCAL_LABEL(NoFloatArguments) + movsd xmm0, [rax + 0] + movsd xmm1, [rax + 16] + movsd xmm2, [rax + 32] + movsd xmm3, [rax + 48] + movsd xmm4, [rax + 64] + movsd xmm5, [rax + 80] + movsd xmm6, [rax + 96] + movsd xmm7, [rax + 112] +LOCAL_LABEL(NoFloatArguments): + call qword ptr [rbx + CallDescrData__pTarget] // call target function + + // Save FP return value + + mov ecx, dword ptr [rbx + CallDescrData__fpReturnSize] + test ecx, ecx + jz LOCAL_LABEL(ReturnsInt) + + cmp ecx, 4 + je LOCAL_LABEL(ReturnsFloat) + cmp ecx, 8 + je LOCAL_LABEL(ReturnsDouble) + +#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + // Struct with two integer eightbytes + cmp ecx, 16 + jne LOCAL_LABEL(NotTwoIntegerEightbytes) + mov qword ptr [rbx+CallDescrData__returnValue], rax + mov qword ptr [rbx+CallDescrData__returnValue + 8], rdx + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(NotTwoIntegerEightbytes): + // Struct with the first eightbyte SSE and the second one integer + cmp ecx, 16 + 1 + jne LOCAL_LABEL(NotFirstSSESecondIntegerEightbyte) + movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0 + mov qword ptr [rbx+CallDescrData__returnValue + 8], rax + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(NotFirstSSESecondIntegerEightbyte): + // Struct with the first eightbyte integer and the second one SSE + cmp ecx, 16 + 2 + jne LOCAL_LABEL(NotFirstIntegerSecondSSEEightbyte) + mov qword ptr [rbx+CallDescrData__returnValue], rax + movsd real8 ptr [rbx+CallDescrData__returnValue + 8], xmm0 + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(NotFirstIntegerSecondSSEEightbyte): + // Struct with two SSE eightbytes + cmp ecx, 16 + 3 + jne LOCAL_LABEL(Epilog) // unexpected + movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0 + movsd real8 ptr [rbx+CallDescrData__returnValue + 8], xmm1 +#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING + + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(ReturnsInt): + mov qword ptr [rbx+CallDescrData__returnValue], rax + +LOCAL_LABEL(Epilog): + lea rsp, [rbp - 8] // deallocate arguments + set_cfa_register rsp, (3*8) + pop_nonvol_reg rbx + pop_nonvol_reg rbp + ret + +LOCAL_LABEL(ReturnsFloat): + movss real4 ptr [rbx+CallDescrData__returnValue], xmm0 + jmp LOCAL_LABEL(Epilog) + +LOCAL_LABEL(ReturnsDouble): + movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0 + jmp LOCAL_LABEL(Epilog) + +NESTED_END CallDescrWorkerInternal, _TEXT + + |