Welcome to mirror list, hosted at ThFree Co, Russian Federation.

CallDescrWorker.asm « arm64 « Runtime « Native « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 06a251280d48937914fe823256567725be47547a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
;; 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.h"

    TEXTAREA

;;-----------------------------------------------------------------------------
;; This helper routine enregisters the appropriate arguments and makes the
;; actual call.
;;
;;  INPUT: x0: pointer to CallDescrData struct
;;
;;-----------------------------------------------------------------------------
;;void RhCallDescrWorker(CallDescrData * pCallDescrData);
    NESTED_ENTRY RhCallDescrWorker

        PROLOG_SAVE_REG_PAIR   fp, lr, #-32!
        PROLOG_SAVE_REG_PAIR   x19, x20, #16

        ;; Save the value of SP before we start pushing any arguments
        mov     x20, sp

        mov     x19, x0 ; save pCallDescrData in x19

        ldr     w1, [x19, #OFFSETOF__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, #OFFSETOF__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, #OFFSETOF__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, #OFFSETOF__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, #OFFSETOF__CallDescrData__pTarget]
        blr     x9

    EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk

        ;; Symbol used to identify thunk call to managed function so the special
        ;; case unwinder can unwind through this function. Sadly we cannot directly
        ;; export this symbol right now because it confuses DIA unwinder to believe
        ;; it's the beginning of a new method, therefore we export the address
        ;; of an auxiliary variable holding the address instead.

        ldr     w3, [x19, #OFFSETOF__CallDescrData__fpReturnSize]

        ;; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
        ldr     x19, [x19, #OFFSETOF__CallDescrData__pReturnBuffer]

        ;; Int return case
        cbz     w3, LIntReturn

        ;; Float return case
        cmp     w3, #4
        beq     LFloatOrDoubleReturn

        ;; Double return case
        cmp     w3, #8
        bne     LCheckHFAReturn

LFloatOrDoubleReturn
        str     d0, [x19]
        b       LReturnDone

LCheckHFAReturn
        cmp     w3, #16
        beq     LFloatOrDoubleHFAReturn
        cmp     w3, #32
        beq     LFloatOrDoubleHFAReturn
        b       LNoHFAReturn

LFloatOrDoubleHFAReturn
        ;;Single/Double HFAReturn  return case
        stp     d0, d1, [x19, #00]
        stp     d2, d3, [x19, #16]
        b       LReturnDone

LNoHFAReturn

        EMIT_BREAKPOINT ; Unreachable

LIntReturn
        ;; Save return value(s) into retbuf for int
        stp     x0, x1, [x19]

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
        ;; Restore the value of SP
        mov     sp, x20

        EPILOG_RESTORE_REG_PAIR x19, x20, #16
        EPILOG_RESTORE_REG_PAIR fp, lr, #32!
        EPILOG_RETURN

    NESTED_END RhCallDescrWorker

    END