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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
// 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.
;; ==++==
;;
;;
;; ==--==
;-----------------------------------------------------------------------------
; Macro used to assign an alternate name to a symbol containing characters normally disallowed in a symbol
; name (e.g. C++ decorated names).
MACRO
SETALIAS $name, $symbol
GBLS $name
$name SETS "|$symbol|"
MEND
;-----------------------------------------------------------------------------
; Macro used to end a function with explicit _End label
MACRO
LEAF_END_MARKED $FuncName
LCLS __EndLabelName
__EndLabelName SETS "$FuncName":CC:"_End"
EXPORT $__EndLabelName
$__EndLabelName
LEAF_END $FuncName
MEND
;-----------------------------------------------------------------------------
; Macro use for enabling C++ to know where to patch code at runtime.
MACRO
PATCH_LABEL $FuncName
$FuncName
EXPORT $FuncName
MEND
;-----------------------------------------------------------------------------
; Macro used to check (in debug builds only) whether the stack is 64-bit aligned (a requirement before calling
; out into C++/OS code). Invoke this directly after your prolog (if the stack frame size is fixed) or directly
; before a call (if you have a frame pointer and a dynamic stack). A breakpoint will be invoked if the stack
; is misaligned.
;
MACRO
CHECK_STACK_ALIGNMENT
#ifdef _DEBUG
push {r0}
add r0, sp, #4
tst r0, #7
pop {r0}
beq %F0
EMIT_BREAKPOINT
0
#endif
MEND
;-----------------------------------------------------------------------------
; The following group of macros assist in implementing prologs and epilogs for methods that set up some
; subclass of TransitionFrame. They ensure that the SP is 64-bit aligned at the conclusion of the prolog and
; provide a helper macro to locate the start of the NegInfo (if there is one) for the frame.
;-----------------------------------------------------------------------------
; Define the prolog for a TransitionFrame-based method. This macro should be called first in the method and
; comprises the entire prolog (i.e. don't modify SP after calling this). Takes the size of the frame's NegInfo
; (which may be zero) and the frame itself. No initialization of the frame is done beyond callee saved
; registers and (non-floating point) argument registers.
;
MACRO
PROLOG_WITH_TRANSITION_BLOCK $extraLocals, $SaveFPArgs, $PushArgRegs
GBLA __PWTB_FloatArgumentRegisters
GBLA __PWTB_StackAlloc
GBLA __PWTB_TransitionBlock
GBLL __PWTB_SaveFPArgs
IF "$SaveFPArgs" != ""
__PWTB_SaveFPArgs SETL $SaveFPArgs
ELSE
__PWTB_SaveFPArgs SETL {true}
ENDIF
IF "$extraLocals" != ""
__PWTB_FloatArgumentRegisters SETA $extraLocals
ELSE
__PWTB_FloatArgumentRegisters SETA 0
ENDIF
IF __PWTB_SaveFPArgs
IF __PWTB_FloatArgumentRegisters:MOD:8 != 0
__PWTB_FloatArgumentRegisters SETA __PWTB_FloatArgumentRegisters + 4
ENDIF
__PWTB_TransitionBlock SETA __PWTB_FloatArgumentRegisters + (SIZEOF__FloatArgumentRegisters + 4) ; padding
ELSE
IF __PWTB_FloatArgumentRegisters:MOD:8 == 0
__PWTB_FloatArgumentRegisters SETA __PWTB_FloatArgumentRegisters + 4; padding
ENDIF
__PWTB_TransitionBlock SETA __PWTB_FloatArgumentRegisters
ENDIF
__PWTB_StackAlloc SETA __PWTB_TransitionBlock
IF "$PushArgRegs" != "DoNotPushArgRegs"
; Spill argument registers.
PROLOG_PUSH {r0-r3}
ENDIF
; Spill callee saved registers and return address.
PROLOG_PUSH {r4-r11,lr}
; Allocate space for the rest of the frame
PROLOG_STACK_ALLOC __PWTB_StackAlloc
IF __PWTB_SaveFPArgs
add r6, sp, #(__PWTB_FloatArgumentRegisters)
vstm r6, {s0-s15}
ENDIF
CHECK_STACK_ALIGNMENT
MEND
;-----------------------------------------------------------------------------
; Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling.
; Since this is a tail call argument registers are restored.
;
MACRO
EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
IF __PWTB_SaveFPArgs
add r6, sp, #(__PWTB_FloatArgumentRegisters)
vldm r6, {s0-s15}
ENDIF
EPILOG_STACK_FREE __PWTB_StackAlloc
EPILOG_POP {r4-r11,lr}
EPILOG_POP {r0-r3}
MEND
;-----------------------------------------------------------------------------
; Provides a matching epilog to PROLOG_WITH_TRANSITION_FRAME and ends by returning to the original caller.
; Since this is not a tail call argument registers are not restored.
;
MACRO
EPILOG_WITH_TRANSITION_BLOCK_RETURN
EPILOG_STACK_FREE __PWTB_StackAlloc
EPILOG_POP {r4-r11,lr}
EPILOG_STACK_FREE 16
EPILOG_RETURN
MEND
|