2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
6 #define INVALIDGCVALUE -0x33333333 // 0CCCCCCCDh - the assembler considers it to be a signed integer constant
27 #if defined(__APPLE__)
28 #define C_FUNC(name) _##name
29 #define EXTERNAL_C_FUNC(name) C_FUNC(name)
30 #define LOCAL_LABEL(name) L##name
32 #define C_FUNC(name) name
33 #define EXTERNAL_C_FUNC(name) C_FUNC(name)@plt
34 #define LOCAL_LABEL(name) .L##name
37 #if defined(__APPLE__)
38 #define C_PLTFUNC(name) _##name
40 #define C_PLTFUNC(name) name@PLT
43 .macro PATCH_LABEL Name
48 .macro LEAF_ENTRY Name, Section
50 #if defined(__APPLE__)
53 .type \Name, %function
59 .macro LEAF_END_MARKED Name, Section
61 .global C_FUNC(\Name\()_End)
62 #if !defined(__APPLE__)
68 .macro LEAF_END Name, Section
69 LEAF_END_MARKED \Name, \Section
72 .macro PREPARE_EXTERNAL_VAR Name, HelperReg
73 mov \HelperReg, [rip + C_FUNC(\Name)@GOTPCREL]
76 .macro push_nonvol_reg Register
78 .cfi_adjust_cfa_offset 8
79 .cfi_rel_offset \Register, 0
82 .macro pop_nonvol_reg Register
84 .cfi_adjust_cfa_offset -8
85 .cfi_restore \Register
88 .macro NESTED_ENTRY Name, Section, Handler
89 LEAF_ENTRY \Name, \Section
90 .ifnc \Handler, NoHandler
91 .cfi_personality 0, \Handler // 4 == DW_EH_PE_udata8 0 == DW_EH_PE_absptr
95 .macro NESTED_END Name, Section
96 LEAF_END \Name, \Section
102 .macro alloc_stack Size
104 lea -\Size(%rsp), %rsp
105 .intel_syntax noprefix
106 .cfi_adjust_cfa_offset \Size
109 .macro free_stack Size
111 lea \Size(%rsp), %rsp
112 .intel_syntax noprefix
113 .cfi_adjust_cfa_offset -\Size
116 .macro set_cfa_register Reg, Offset
117 .cfi_def_cfa_register \Reg
118 .cfi_def_cfa_offset \Offset
121 .macro save_reg_postrsp Reg, Offset
123 mov qword ptr [rsp + __Offset], \Reg
124 .cfi_rel_offset \Reg, __Offset
127 .macro restore_reg Reg, Offset
129 mov \Reg, [rsp + __Offset]
133 .macro save_xmm128_postrsp Reg, Offset
135 movdqa [rsp + __Offset], \Reg
136 // NOTE: We cannot use ".cfi_rel_offset \Reg, __Offset" here,
137 // the xmm registers are not supported by the libunwind
140 .macro restore_xmm128 Reg, ofs
142 movdqa \Reg, [rsp + __Offset]
143 // NOTE: We cannot use ".cfi_restore \Reg" here,
144 // the xmm registers are not supported by the libunwind
148 .macro POP_CALLEE_SAVED_REGISTERS
159 .macro push_register Reg
161 .cfi_adjust_cfa_offset 8
166 .cfi_adjust_cfa_offset 8
169 .macro push_argument_register Reg
173 .macro PUSH_ARGUMENT_REGISTERS
175 push_argument_register r9
176 push_argument_register r8
177 push_argument_register rdx
178 push_argument_register rcx
179 push_argument_register rsi
180 push_argument_register rdi
184 .macro pop_register Reg
186 .cfi_adjust_cfa_offset -8
189 .macro pop_argument_register Reg
193 .macro POP_ARGUMENT_REGISTERS
195 pop_argument_register rdi
196 pop_argument_register rsi
197 pop_argument_register rcx
198 pop_argument_register rdx
199 pop_argument_register r8
200 pop_argument_register r9
204 .macro SAVE_FLOAT_ARGUMENT_REGISTERS ofs
206 save_xmm128_postrsp xmm0, \ofs
207 save_xmm128_postrsp xmm1, \ofs + 0x10
208 save_xmm128_postrsp xmm2, \ofs + 0x20
209 save_xmm128_postrsp xmm3, \ofs + 0x30
210 save_xmm128_postrsp xmm4, \ofs + 0x40
211 save_xmm128_postrsp xmm5, \ofs + 0x50
212 save_xmm128_postrsp xmm6, \ofs + 0x60
213 save_xmm128_postrsp xmm7, \ofs + 0x70
217 .macro RESTORE_FLOAT_ARGUMENT_REGISTERS ofs
219 restore_xmm128 xmm0, \ofs
220 restore_xmm128 xmm1, \ofs + 0x10
221 restore_xmm128 xmm2, \ofs + 0x20
222 restore_xmm128 xmm3, \ofs + 0x30
223 restore_xmm128 xmm4, \ofs + 0x40
224 restore_xmm128 xmm5, \ofs + 0x50
225 restore_xmm128 xmm6, \ofs + 0x60
226 restore_xmm128 xmm7, \ofs + 0x70
232 // (stack parameters)
235 // CalleeSavedRegisters::rbp
236 // CalleeSavedRegisters::rbx
237 // CalleeSavedRegisters::r15
238 // CalleeSavedRegisters::r14
239 // CalleeSavedRegisters::r13
240 // CalleeSavedRegisters::r12
241 // ArgumentRegisters::r9
242 // ArgumentRegisters::r8
243 // ArgumentRegisters::rcx
244 // ArgumentRegisters::rdx
245 // ArgumentRegisters::rsi
246 // ArgumentRegisters::rdi <- __PWTB_StackAlloc, __PWTB_TransitionBlock
247 // padding to align xmm save area
255 // xmm0 <- __PWTB_FloatArgumentRegisters
256 // extra locals + padding to qword align
257 .macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, stackAllocOnEntry = 0, stackAllocSpill1, stackAllocSpill2, stackAllocSpill3
259 __PWTB_FloatArgumentRegisters = \extraLocals
261 .if ((__PWTB_FloatArgumentRegisters % 16) != 0)
262 __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8
265 __PWTB_StackAlloc = __PWTB_FloatArgumentRegisters + 8 * 16 + 8 // 8 floating point registers
266 __PWTB_TransitionBlock = __PWTB_StackAlloc
268 .if \stackAllocOnEntry >= 4*8
269 .error "Max supported stackAllocOnEntry is 3*8"
272 .if \stackAllocOnEntry > 0
273 .cfi_adjust_cfa_offset \stackAllocOnEntry
276 // PUSH_CALLEE_SAVED_REGISTERS expanded here
278 .if \stackAllocOnEntry < 8
283 .if \stackAllocOnEntry < 2*8
287 .if \stackAllocOnEntry < 3*8
296 PUSH_ARGUMENT_REGISTERS
298 .if \stackAllocOnEntry >= 3*8
299 mov \stackAllocSpill3, [rsp + 0x48]
300 save_reg_postrsp r15, 0x48
303 .if \stackAllocOnEntry >= 2*8
304 mov \stackAllocSpill2, [rsp + 0x50]
305 save_reg_postrsp rbx, 0x50
308 .if \stackAllocOnEntry >= 8
309 mov \stackAllocSpill1, [rsp + 0x58]
310 save_reg_postrsp rbp, 0x58
311 lea rbp, [rsp + 0x58]
314 alloc_stack __PWTB_StackAlloc
315 SAVE_FLOAT_ARGUMENT_REGISTERS __PWTB_FloatArgumentRegisters
321 .macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
323 RESTORE_FLOAT_ARGUMENT_REGISTERS __PWTB_FloatArgumentRegisters
324 free_stack __PWTB_StackAlloc
325 POP_ARGUMENT_REGISTERS
326 POP_CALLEE_SAVED_REGISTERS