diff options
Diffstat (limited to 'src/vm/arm64/CallDescrWorkerARM64.asm')
-rw-r--r-- | src/vm/arm64/CallDescrWorkerARM64.asm | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/vm/arm64/CallDescrWorkerARM64.asm b/src/vm/arm64/CallDescrWorkerARM64.asm new file mode 100644 index 0000000000..b9f8a6090d --- /dev/null +++ b/src/vm/arm64/CallDescrWorkerARM64.asm @@ -0,0 +1,138 @@ +; 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 "ksarm64.h" + +#include "asmconstants.h" + + + + IMPORT CallDescrWorkerUnwindFrameChainHandler +;;----------------------------------------------------------------------------- +;; This helper routine enregisters the appropriate arguments and makes the +;; actual call. +;;----------------------------------------------------------------------------- +;;void CallDescrWorkerInternal(CallDescrData * pCallDescrData); + NESTED_ENTRY CallDescrWorkerInternal,,CallDescrWorkerUnwindFrameChainHandler + PROLOG_SAVE_REG_PAIR fp, lr, #-32! + PROLOG_SAVE_REG x19, #16 ;the stack slot at sp+24 is empty for 16 byte alligment + + mov x19, x0 ; save pCallDescrData in x19 + + ldr w1, [x19,#CallDescrData__numStackSlots] + cbz w1, Ldonestack + + ;; Add frame padding to ensure frame size is a multiple of 16 (a requirement of the OS ABI). + ;; We push two registers (above) and numStackSlots arguments (below). If this comes to an odd number + ;; of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set, + ;; extend the stack another eight bytes". + ldr x0, [x19,#CallDescrData__pSrc] + add x0, x0, x1 lsl #3 ; pSrcEnd=pSrc+8*numStackSlots + ands x2, x1, #1 + beq Lstackloop + + ;; This loop copies numStackSlots words + ;; from [pSrcEnd-8,pSrcEnd-16,...] to [sp-8,sp-16,...] + + ;; pad and store one stack slot as number of slots are odd + ldr x4, [x0,#-8]! + str x4, [sp,#-16]! + subs x1, x1, #1 + beq Ldonestack +Lstackloop + ldp x2, x4, [x0,#-16]! + stp x2, x4, [sp,#-16]! + subs x1, x1, #2 + bne Lstackloop +Ldonestack + + ;; 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 + 64] + ;; into x0, ..., x7, x8 + + 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] + + ;; call pTarget + ldr x9, [x19,#CallDescrData__pTarget] + blr x9 + + ldr w3, [x19,#CallDescrData__fpReturnSize] + + ;; Int return case + cbz w3, LIntReturn + + ;; Float return case + cmp w3, #4 + beq LFloatReturn + + ;; Double return case + cmp w3, #8 + bne LNoDoubleReturn + +LFloatReturn + str d0, [x19, #(CallDescrData__returnValue + 0)] + b LReturnDone + +LNoDoubleReturn + + ;;FloatHFAReturn return case + cmp w3, #16 + bne LNoFloatHFAReturn + + stp s0, s1, [x19, #(CallDescrData__returnValue + 0)] + stp s2, s3, [x19, #(CallDescrData__returnValue + 0x08)] + b LReturnDone +LNoFloatHFAReturn + + ;;DoubleHFAReturn return case + cmp w3, #32 + bne LNoDoubleHFAReturn + + stp d0, d1, [x19, #(CallDescrData__returnValue + 0)] + stp d2, d3, [x19, #(CallDescrData__returnValue + 0x10)] + b LReturnDone + +LNoDoubleHFAReturn + + EMIT_BREAKPOINT ; Unreachable + +LIntReturn + ;; Save return value(s) into retbuf for int + stp x0,x1, [x19, #(CallDescrData__returnValue + 0)] + +LReturnDone + +#ifdef _DEBUG + ;; trash the floating point registers to ensure that the HFA return values + ;; won't survive by accident + ldp d0, d1, [sp] + ldp d2, d3, [sp, #16] +#endif + + EPILOG_STACK_RESTORE + EPILOG_RESTORE_REG x19, #16 ;the stack slot at sp+24 is empty for 16 byte alligment + EPILOG_RESTORE_REG_PAIR fp, lr, #32! + EPILOG_RETURN + NESTED_END + + END |