Implement 64-bit MacroAssembler::probe support for Windows.
[WebKit-https.git] / Source / JavaScriptCore / jit / JITStubsMSVC64.asm
1 ;/*
2 ; Copyright (C) 2014 Apple Inc. All rights reserved.
3 ;
4 ; Redistribution and use in source and binary forms, with or without
5 ; modification, are permitted provided that the following conditions
6 ; are met:
7 ; 1. Redistributions of source code must retain the above copyright
8 ;    notice, this list of conditions and the following disclaimer.
9 ; 2. Redistributions in binary form must reproduce the above copyright
10 ;    notice, this list of conditions and the following disclaimer in the
11 ;    documentation and/or other materials provided with the distribution.
12 ;
13 ; THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 ; PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 ; OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 ;*/
25
26 EXTERN getHostCallReturnValueWithExecState : near
27
28 PUBLIC getHostCallReturnValue
29 PUBLIC ctiMasmProbeTrampoline
30
31 _TEXT   SEGMENT
32
33 getHostCallReturnValue PROC
34     lea rcx, [rsp - 8]
35     ; Allocate space for all 4 parameter registers, and align stack pointer to 16 bytes boundary by allocating another 8 bytes.
36     ; The stack alignment is needed to fix a crash in the CRT library on a floating point instruction.
37     sub rsp, 40
38     call getHostCallReturnValueWithExecState
39     add rsp, 40
40     ret
41 getHostCallReturnValue ENDP
42
43 ; The following constants must match the x86_64 version in MacroAssemblerX86Common.cpp.
44 PTR_SIZE EQU 8
45
46 PROBE_PROBE_FUNCTION_OFFSET EQU (0 * PTR_SIZE)
47 PROBE_ARG_OFFSET EQU (1 * PTR_SIZE)
48 PROBE_INIT_STACK_FUNCTION_OFFSET EQU (2 * PTR_SIZE)
49 PROBE_INIT_STACK_ARG_OFFSET EQU (3 * PTR_SIZE)
50
51 PROBE_FIRST_GPR_OFFSET EQU (4 * PTR_SIZE)
52 PROBE_CPU_EAX_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (0 * PTR_SIZE))
53 PROBE_CPU_ECX_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (1 * PTR_SIZE))
54 PROBE_CPU_EDX_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (2 * PTR_SIZE))
55 PROBE_CPU_EBX_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (3 * PTR_SIZE))
56 PROBE_CPU_ESP_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (4 * PTR_SIZE))
57 PROBE_CPU_EBP_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (5 * PTR_SIZE))
58 PROBE_CPU_ESI_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (6 * PTR_SIZE))
59 PROBE_CPU_EDI_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (7 * PTR_SIZE))
60
61 PROBE_CPU_R8_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (8 * PTR_SIZE))
62 PROBE_CPU_R9_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (9 * PTR_SIZE))
63 PROBE_CPU_R10_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (10 * PTR_SIZE))
64 PROBE_CPU_R11_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (11 * PTR_SIZE))
65 PROBE_CPU_R12_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (12 * PTR_SIZE))
66 PROBE_CPU_R13_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (13 * PTR_SIZE))
67 PROBE_CPU_R14_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (14 * PTR_SIZE))
68 PROBE_CPU_R15_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (15 * PTR_SIZE))
69 PROBE_FIRST_SPR_OFFSET EQU (PROBE_FIRST_GPR_OFFSET + (16 * PTR_SIZE))
70
71 PROBE_CPU_EIP_OFFSET EQU (PROBE_FIRST_SPR_OFFSET + (0 * PTR_SIZE))
72 PROBE_CPU_EFLAGS_OFFSET EQU (PROBE_FIRST_SPR_OFFSET + (1 * PTR_SIZE))
73 PROBE_FIRST_XMM_OFFSET EQU (PROBE_FIRST_SPR_OFFSET + (2 * PTR_SIZE))
74
75 XMM_SIZE EQU 8
76 PROBE_CPU_XMM0_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (0 * XMM_SIZE))
77 PROBE_CPU_XMM1_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (1 * XMM_SIZE))
78 PROBE_CPU_XMM2_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (2 * XMM_SIZE))
79 PROBE_CPU_XMM3_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (3 * XMM_SIZE))
80 PROBE_CPU_XMM4_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (4 * XMM_SIZE))
81 PROBE_CPU_XMM5_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (5 * XMM_SIZE))
82 PROBE_CPU_XMM6_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (6 * XMM_SIZE))
83 PROBE_CPU_XMM7_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (7 * XMM_SIZE))
84
85 PROBE_CPU_XMM8_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (8 * XMM_SIZE))
86 PROBE_CPU_XMM9_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (9 * XMM_SIZE))
87 PROBE_CPU_XMM10_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (10 * XMM_SIZE))
88 PROBE_CPU_XMM11_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (11 * XMM_SIZE))
89 PROBE_CPU_XMM12_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (12 * XMM_SIZE))
90 PROBE_CPU_XMM13_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (13 * XMM_SIZE))
91 PROBE_CPU_XMM14_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (14 * XMM_SIZE))
92 PROBE_CPU_XMM15_OFFSET EQU (PROBE_FIRST_XMM_OFFSET + (15 * XMM_SIZE))
93 PROBE_SIZE EQU (PROBE_CPU_XMM15_OFFSET + XMM_SIZE)
94
95 PROBE_EXECUTOR_OFFSET EQU PROBE_SIZE ; Stash the executeProbe function pointer at the end of the ProbeContext.
96
97 OUT_SIZE EQU (5 * PTR_SIZE)
98
99 ctiMasmProbeTrampoline PROC
100     pushfq
101
102     ; MacroAssemblerX86Common::probe() has already generated code to store some values.
103     ; Together with the rflags pushed above, the top of stack now looks like this:
104     ;     rsp[0 * ptrSize]: rflags
105     ;     rsp[1 * ptrSize]: return address / saved rip
106     ;     rsp[2 * ptrSize]: saved rbx
107     ;     rsp[3 * ptrSize]: saved rdx
108     ;     rsp[4 * ptrSize]: saved rcx
109     ;     rsp[5 * ptrSize]: saved rax
110     ;
111     ; Incoming registers contain:
112     ;     rcx: Probe::executeProbe
113     ;     rdx: probe function
114     ;     rbx: probe arg
115     ;     rax: scratch (was ctiMasmProbeTrampoline)
116
117     mov rax, rsp 
118     sub rsp, PROBE_SIZE + OUT_SIZE
119
120     ; The X86_64 ABI specifies that the worse case stack alignment requirement is 32 bytes.
121     and rsp, not 01fh
122     ; Since sp points to the ProbeContext, we've ensured that it's protected from interrupts before we initialize it.
123
124     mov [PROBE_CPU_EBP_OFFSET + rsp], rbp
125     mov rbp, rsp ; Save the ProbeContext*.
126
127     mov [PROBE_EXECUTOR_OFFSET + rbp], rcx
128     mov [PROBE_PROBE_FUNCTION_OFFSET + rbp], rdx
129     mov [PROBE_ARG_OFFSET + rbp], rbx
130     mov [PROBE_CPU_ESI_OFFSET + rbp], rsi
131     mov [PROBE_CPU_EDI_OFFSET + rbp], rdi
132
133     mov rcx, [0 * PTR_SIZE + rax]
134     mov [PROBE_CPU_EFLAGS_OFFSET + rbp], rcx
135     mov rcx, [1 *  PTR_SIZE + rax]
136     mov [PROBE_CPU_EIP_OFFSET + rbp], rcx
137     mov rcx, [2 * PTR_SIZE + rax]
138     mov [PROBE_CPU_EBX_OFFSET + rbp], rcx
139     mov rcx, [3 * PTR_SIZE + rax]
140     mov [PROBE_CPU_EDX_OFFSET + rbp], rcx
141     mov rcx, [4 * PTR_SIZE + rax]
142     mov [PROBE_CPU_ECX_OFFSET + rbp], rcx
143     mov rcx, [5 * PTR_SIZE + rax]
144     mov [PROBE_CPU_EAX_OFFSET + rbp], rcx
145
146     mov rcx, rax
147     add rcx, 6 * PTR_SIZE
148     mov [PROBE_CPU_ESP_OFFSET + rbp], rcx
149
150     mov [PROBE_CPU_R8_OFFSET + rbp], r8
151     mov [PROBE_CPU_R9_OFFSET + rbp], r9
152     mov [PROBE_CPU_R10_OFFSET + rbp], r10
153     mov [PROBE_CPU_R11_OFFSET + rbp], r11
154     mov [PROBE_CPU_R12_OFFSET + rbp], r12
155     mov [PROBE_CPU_R13_OFFSET + rbp], r13
156     mov [PROBE_CPU_R14_OFFSET + rbp], r14
157     mov [PROBE_CPU_R15_OFFSET + rbp], r15
158
159     movq qword ptr [PROBE_CPU_XMM0_OFFSET + rbp], xmm0
160     movq qword ptr [PROBE_CPU_XMM1_OFFSET + rbp], xmm1
161     movq qword ptr [PROBE_CPU_XMM2_OFFSET + rbp], xmm2
162     movq qword ptr [PROBE_CPU_XMM3_OFFSET + rbp], xmm3
163     movq qword ptr [PROBE_CPU_XMM4_OFFSET + rbp], xmm4
164     movq qword ptr [PROBE_CPU_XMM5_OFFSET + rbp], xmm5
165     movq qword ptr [PROBE_CPU_XMM6_OFFSET + rbp], xmm6
166     movq qword ptr [PROBE_CPU_XMM7_OFFSET + rbp], xmm7
167     movq qword ptr [PROBE_CPU_XMM8_OFFSET + rbp], xmm8
168     movq qword ptr [PROBE_CPU_XMM9_OFFSET + rbp], xmm9
169     movq qword ptr [PROBE_CPU_XMM10_OFFSET + rbp], xmm10
170     movq qword ptr [PROBE_CPU_XMM11_OFFSET + rbp], xmm11
171     movq qword ptr [PROBE_CPU_XMM12_OFFSET + rbp], xmm12
172     movq qword ptr [PROBE_CPU_XMM13_OFFSET + rbp], xmm13
173     movq qword ptr [PROBE_CPU_XMM14_OFFSET + rbp], xmm14
174     movq qword ptr [PROBE_CPU_XMM15_OFFSET + rbp], xmm15
175
176     mov rcx, rbp ; the Probe::State* arg.
177     sub rsp, 32 ; shadow space
178     call qword ptr[PROBE_EXECUTOR_OFFSET + rbp]
179     add rsp, 32
180
181     ; Make sure the ProbeContext is entirely below the result stack pointer so
182     ; that register values are still preserved when we call the initializeStack
183     ; function.
184     mov rcx, PROBE_SIZE + OUT_SIZE
185     mov rax, rbp
186     mov rdx, [PROBE_CPU_ESP_OFFSET + rbp]
187     add rax, rcx
188     cmp rdx, rax 
189     jge ctiMasmProbeTrampolineProbeContextIsSafe
190
191     ; Allocate a safe place on the stack below the result stack pointer to stash the ProbeContext.
192     sub rdx, rcx
193     and rdx, not 01fh ; Keep the stack pointer 32 bytes aligned.
194     xor rax, rax
195     mov rsp, rdx
196
197     mov rcx, PROBE_SIZE
198
199     ; Copy the ProbeContext to the safe place.
200     ctiMasmProbeTrampolineCopyLoop:
201     mov rdx, [rbp + rax]
202     mov [rsp + rax], rdx
203     add rax, PTR_SIZE
204     cmp rcx, rax
205     jg ctiMasmProbeTrampolineCopyLoop
206
207     mov rbp, rsp
208
209     ; Call initializeStackFunction if present.
210     ctiMasmProbeTrampolineProbeContextIsSafe:
211     xor rcx, rcx
212     add rcx, [PROBE_INIT_STACK_FUNCTION_OFFSET + rbp]
213     je ctiMasmProbeTrampolineRestoreRegisters
214
215     mov rdx, rcx
216     mov rcx, rbp ; the Probe::State* arg.
217     sub rsp, 32 ; shadow space
218     call rdx
219     add rsp, 32
220
221     ctiMasmProbeTrampolineRestoreRegisters:
222
223     ; To enable probes to modify register state, we copy all registers
224     ; out of the ProbeContext before returning.
225
226     mov rdx, [PROBE_CPU_EDX_OFFSET + rbp]
227     mov rbx, [PROBE_CPU_EBX_OFFSET + rbp]
228     mov rsi, [PROBE_CPU_ESI_OFFSET + rbp]
229     mov rdi, [PROBE_CPU_EDI_OFFSET + rbp]
230
231     mov r8, [PROBE_CPU_R8_OFFSET + rbp]
232     mov r9, [PROBE_CPU_R9_OFFSET + rbp]
233     mov r10, [PROBE_CPU_R10_OFFSET + rbp]
234     mov r11, [PROBE_CPU_R11_OFFSET + rbp]
235     mov r12, [PROBE_CPU_R12_OFFSET + rbp]
236     mov r13, [PROBE_CPU_R13_OFFSET + rbp]
237     mov r14, [PROBE_CPU_R14_OFFSET + rbp]
238     mov r15, [PROBE_CPU_R15_OFFSET + rbp]
239
240     movq xmm0, qword ptr[PROBE_CPU_XMM0_OFFSET + rbp]
241     movq xmm1, qword ptr[PROBE_CPU_XMM1_OFFSET + rbp]
242     movq xmm2, qword ptr[PROBE_CPU_XMM2_OFFSET + rbp]
243     movq xmm3, qword ptr[PROBE_CPU_XMM3_OFFSET + rbp]
244     movq xmm4, qword ptr[PROBE_CPU_XMM4_OFFSET + rbp]
245     movq xmm5, qword ptr[PROBE_CPU_XMM5_OFFSET + rbp]
246     movq xmm6, qword ptr[PROBE_CPU_XMM6_OFFSET + rbp]
247     movq xmm7, qword ptr[PROBE_CPU_XMM7_OFFSET + rbp]
248     movq xmm8, qword ptr[PROBE_CPU_XMM8_OFFSET + rbp]
249     movq xmm9, qword ptr[PROBE_CPU_XMM9_OFFSET + rbp]
250     movq xmm10, qword ptr[PROBE_CPU_XMM10_OFFSET + rbp]
251     movq xmm11, qword ptr[PROBE_CPU_XMM11_OFFSET + rbp]
252     movq xmm12, qword ptr[PROBE_CPU_XMM12_OFFSET + rbp]
253     movq xmm13, qword ptr[PROBE_CPU_XMM13_OFFSET + rbp]
254     movq xmm14, qword ptr[PROBE_CPU_XMM14_OFFSET + rbp]
255     movq xmm15, qword ptr[PROBE_CPU_XMM15_OFFSET + rbp]
256
257     ; There are 6 more registers left to restore:
258     ;     rax, rcx, rbp, rsp, rip, and rflags.
259
260     ; The restoration process at ctiMasmProbeTrampolineEnd below works by popping
261     ; 5 words off the stack into rflags, rax, rcx, rbp, and rip. These 5 words need
262     ; to be pushed on top of the final esp value so that just by popping the 5 words,
263     ; we'll get the esp that the probe wants to set. Let's call this area (for storing
264     ; these 5 words) the restore area.
265     mov rcx, [PROBE_CPU_ESP_OFFSET + rbp]
266     sub rcx, 5 * PTR_SIZE
267
268     ; rcx now points to the restore area.
269
270     ; Copy remaining restore values from the ProbeContext to the restore area.
271     ; Note: We already ensured above that the ProbeContext is in a safe location before
272     ; calling the initializeStackFunction. The initializeStackFunction is not allowed to
273     ; change the stack pointer again.
274     mov rax, [PROBE_CPU_EFLAGS_OFFSET + rbp]
275     mov [0 * PTR_SIZE + rcx], rax
276     mov rax, [PROBE_CPU_EAX_OFFSET + rbp]
277     mov [1 * PTR_SIZE + rcx], rax
278     mov rax, [PROBE_CPU_ECX_OFFSET + rbp] 
279     mov [2 * PTR_SIZE + rcx], rax
280     mov rax, [PROBE_CPU_EBP_OFFSET + rbp]
281     mov [3 * PTR_SIZE + rcx], rax
282     mov rax, [PROBE_CPU_EIP_OFFSET + rbp]
283     mov [4 * PTR_SIZE + rcx], rax
284     mov rsp, rcx
285
286     ; Do the remaining restoration by popping off the restore area.
287     popfq
288     pop rax
289     pop rcx
290     pop rbp
291     ret
292 ctiMasmProbeTrampoline ENDP
293
294 _TEXT   ENDS
295
296 END