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
|
;; 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.
;;-----------------------------------------------------------------------------
;;void RhCallDescrWorker(CallDescrData * pCallDescrData);
NESTED_ENTRY RhCallDescrWorker
PROLOG_PUSH {r4,r5,r7,lr}
PROLOG_STACK_SAVE r7
mov r5,r0 ; save pCallDescrData in r5
ldr r1, [r5,#OFFSETOF__CallDescrData__numStackSlots]
cbz r1, Ldonestack
;; Add frame padding to ensure frame size is a multiple of 8 (a requirement of the OS ABI).
;; We push four 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 four bytes".
lsls r2, r1, #2
and r3, r2, #4
sub sp, sp, r3
;; This loop copies numStackSlots words
;; from [pSrcEnd-4,pSrcEnd-8,...] to [sp-4,sp-8,...]
ldr r0, [r5,#OFFSETOF__CallDescrData__pSrc]
add r0,r0,r2
Lstackloop
ldr r2, [r0,#-4]!
str r2, [sp,#-4]!
subs r1, r1, #1
bne Lstackloop
Ldonestack
;; If FP arguments are supplied in registers (r3 != NULL) then initialize all of them from the pointer
;; given in r3. Do not use "it" since it faults in floating point even when the instruction is not executed.
ldr r3, [r5,#OFFSETOF__CallDescrData__pFloatArgumentRegisters]
cbz r3, LNoFloatingPoint
vldm r3, {s0-s15}
LNoFloatingPoint
;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 12]
;; into r0, ..., r3
ldr r4, [r5,#OFFSETOF__CallDescrData__pArgumentRegisters]
ldm r4, {r0-r3}
CHECK_STACK_ALIGNMENT
;; call pTarget
;; Note that remoting expect target in r4.
ldr r4, [r5,#OFFSETOF__CallDescrData__pTarget]
blx r4
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 r3, [r5,#OFFSETOF__CallDescrData__fpReturnSize]
;; Save FP return value if appropriate
cbz r3, LFloatingPointReturnDone
;; Float return case
;; Do not use "it" since it faults in floating point even when the instruction is not executed.
cmp r3, #4
bne LNoFloatReturn
vmov r0, s0
b LFloatingPointReturnDone
LNoFloatReturn
;; Double return case
;; Do not use "it" since it faults in floating point even when the instruction is not executed.
cmp r3, #8
bne LNoDoubleReturn
vmov r0, r1, s0, s1
b LFloatingPointReturnDone
LNoDoubleReturn
; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
ldr r2, [r5, #OFFSETOF__CallDescrData__pReturnBuffer]
cmp r3, #16
bne LNoFloatHFAReturn
vstm r2, {s0-s3}
b LReturnDone
LNoFloatHFAReturn
cmp r3, #32
bne LNoDoubleHFAReturn
vstm r2, {d0-d3}
b LReturnDone
LNoDoubleHFAReturn
EMIT_BREAKPOINT ; Unreachable
LFloatingPointReturnDone
; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
ldr r5, [r5, #OFFSETOF__CallDescrData__pReturnBuffer]
;; Save return value into retbuf
str r0, [r5, #(0)]
str r1, [r5, #(4)]
LReturnDone
#ifdef _DEBUG
;; trash the floating point registers to ensure that the HFA return values
;; won't survive by accident
vldm sp, {d0-d3}
#endif
EPILOG_STACK_RESTORE r7
EPILOG_POP {r4,r5,r7,pc}
NESTED_END RhCallDescrWorker
END
|