ms-manual.xml: Put stray ':' inside para.
[valgrind.git] / coregrind / m_dispatch / dispatch-amd64-darwin.S
blob7dc06a84e717543d9b49d4df6b9fa3691452350b
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                      dispatch-amd64-darwin.S ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
11   Copyright (C) 2000-2017 Julian Seward 
12      jseward@acm.org
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, see <http://www.gnu.org/licenses/>.
27   The GNU General Public License is contained in the file COPYING.
30 #include "pub_core_basics_asm.h"
32 #if defined(VGP_amd64_darwin)
34 #include "pub_core_dispatch_asm.h"
35 #include "pub_core_transtab_asm.h"
36 #include "libvex_guest_offsets.h"       /* for OFFSET_amd64_RIP */
39 /*------------------------------------------------------------*/
40 /*---                                                      ---*/
41 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
42 /*--- used to run all translations,                        ---*/
43 /*--- including no-redir ones.                             ---*/
44 /*---                                                      ---*/
45 /*------------------------------------------------------------*/
47 /*----------------------------------------------------*/
48 /*--- Entry and preamble (set everything up)       ---*/
49 /*----------------------------------------------------*/
51 /* signature:
52 void VG_(disp_run_translations)( UWord* two_words,
53                                  void*  guest_state, 
54                                  Addr   host_addr );
56 .text
57 .globl VG_(disp_run_translations)
58 VG_(disp_run_translations):
59         /* %rdi holds two_words    */
60         /* %rsi holds guest_state  */
61         /* %rdx holds host_addr    */
63         /* The preamble */
65         /* Save integer registers, since this is a pseudo-function. */
66         pushq   %rax
67         pushq   %rbx
68         pushq   %rcx
69         pushq   %rdx
70         pushq   %rsi
71         pushq   %rbp
72         pushq   %r8
73         pushq   %r9
74         pushq   %r10
75         pushq   %r11
76         pushq   %r12
77         pushq   %r13
78         pushq   %r14
79         pushq   %r15
80         /* %rdi must be saved last */
81         pushq   %rdi
83         /* Get the host CPU in the state expected by generated code. */
85         /* set host FPU control word to the default mode expected 
86            by VEX-generated code.  See comments in libvex.h for
87            more info. */
88         finit
89         pushq   $0x027F
90         fldcw   (%rsp)
91         addq    $8, %rsp
92         
93         /* set host SSE control word to the default mode expected 
94            by VEX-generated code. */
95         pushq   $0x1F80
96         ldmxcsr (%rsp)
97         addq    $8, %rsp
99         /* set dir flag to known value */
100         cld
102         /* Set up the guest state pointer */
103         movq    %rsi, %rbp
105         /* and jump into the code cache.  Chained translations in
106            the code cache run, until for whatever reason, they can't
107            continue.  When that happens, the translation in question
108            will jump (or call) to one of the continuation points
109            VG_(cp_...) below. */
110         jmpq    *%rdx
111         /*NOTREACHED*/  
113 /*----------------------------------------------------*/
114 /*--- Postamble and exit.                          ---*/
115 /*----------------------------------------------------*/
117 postamble:
118         /* At this point, %rax and %rdx contain two
119            words to be returned to the caller.  %rax
120            holds a TRC value, and %rdx optionally may
121            hold another word (for CHAIN_ME exits, the
122            address of the place to patch.) */
123         
124         /* We're leaving.  Check that nobody messed with %mxcsr
125            or %fpucw.  We can't mess with %rax or %rdx here as they
126            hold the tentative return values, but any others are OK. */
127 #if !defined(ENABLE_INNER)
128         /* This check fails for self-hosting, so skip in that case */
129         pushq   $0
130         fstcw   (%rsp)
131         cmpl    $0x027F, (%rsp)
132         popq    %r15 /* get rid of the word without trashing %rflags */
133         jnz     invariant_violation
134 #endif
135         pushq   $0
136         stmxcsr (%rsp)
137         andl    $0xFFFFFFC0, (%rsp)  /* mask out status flags */
138         cmpl    $0x1F80, (%rsp)
139         popq    %r15
140         jnz     invariant_violation
141         /* otherwise we're OK */
142         jmp     remove_frame
143 invariant_violation:
144         movq    $VG_TRC_INVARIANT_FAILED, %rax
145         movq    $0, %rdx
147 remove_frame:
148         /* Pop %rdi, stash return values */
149         popq    %rdi
150         movq    %rax, 0(%rdi)
151         movq    %rdx, 8(%rdi)
152         /* Now pop everything else */
153         popq    %r15
154         popq    %r14
155         popq    %r13
156         popq    %r12
157         popq    %r11
158         popq    %r10
159         popq    %r9
160         popq    %r8
161         popq    %rbp
162         popq    %rsi
163         popq    %rdx
164         popq    %rcx
165         popq    %rbx
166         popq    %rax
167         ret     
168         
169 /*----------------------------------------------------*/
170 /*--- Continuation points                          ---*/
171 /*----------------------------------------------------*/
173 /* ------ Chain me to slow entry point ------ */
174 .globl VG_(disp_cp_chain_me_to_slowEP)
175 VG_(disp_cp_chain_me_to_slowEP):
176         /* We got called.  The return address indicates
177            where the patching needs to happen.  Collect
178            the return address and, exit back to C land,
179            handing the caller the pair (Chain_me_S, RA) */
180         movq    $VG_TRC_CHAIN_ME_TO_SLOW_EP, %rax
181         popq    %rdx
182         /* 10 = movabsq $VG_(disp_chain_me_to_slowEP), %r11;
183            3  = call *%r11 */
184         subq    $10+3, %rdx
185         jmp     postamble
187 /* ------ Chain me to fast entry point ------ */
188 .globl VG_(disp_cp_chain_me_to_fastEP)
189 VG_(disp_cp_chain_me_to_fastEP):
190         /* We got called.  The return address indicates
191            where the patching needs to happen.  Collect
192            the return address and, exit back to C land,
193            handing the caller the pair (Chain_me_F, RA) */
194         movq    $VG_TRC_CHAIN_ME_TO_FAST_EP, %rax
195         popq    %rdx
196         /* 10 = movabsq $VG_(disp_chain_me_to_fastEP), %r11;
197            3  = call *%r11 */
198         subq    $10+3, %rdx
199         jmp     postamble
201 /* ------ Indirect but boring jump ------ */
202 .global VG_(disp_cp_xindir)
203 VG_(disp_cp_xindir):
204         /* Where are we going? */
205         movq    OFFSET_amd64_RIP(%rbp), %rax    // "guest"
207         /* stats only */
208         movabsq $VG_(stats__n_xIndirs_32), %r8
209         addl    $1, (%r8)
211         // LIVE: %rbp (guest state ptr), %rax (guest address to go to).
212         // We use 5 temporaries:
213         //   %r9 (to point at the relevant FastCacheSet),
214         //   %r10, %r11 and %r12 (scratch).
215         //   %r8 (scratch address)
217         /* Try a fast lookup in the translation cache.  This is pretty much
218            a handcoded version of VG_(lookupInFastCache). */
220         // Compute %r9 = VG_TT_FAST_HASH(guest)
221         movq    %rax, %r9               // guest
222         shrq    $VG_TT_FAST_BITS, %r9   // (guest >> VG_TT_FAST_BITS)
223         xorq    %rax, %r9               // (guest >> VG_TT_FAST_BITS) ^ guest
224         andq    $VG_TT_FAST_MASK, %r9   // setNo
226         // Compute %r9 = &VG_(tt_fast)[%r9]
227         shlq    $VG_FAST_CACHE_SET_BITS, %r9  // setNo * sizeof(FastCacheSet)
228         movabsq $VG_(tt_fast), %r10           // &VG_(tt_fast)[0]
229         leaq    (%r10, %r9), %r9              // &VG_(tt_fast)[setNo]
231         // LIVE: %rbp (guest state ptr), %rax (guest addr), %r9 (cache set)
232         // try way 0
233         cmpq    %rax, FCS_g0(%r9)   // cmp against .guest0
234         jnz     1f
235         // hit at way 0
236         jmp    *FCS_h0(%r9)         // goto .host0
237         ud2
239 1:      // try way 1
240         cmpq    %rax, FCS_g1(%r9)   // cmp against .guest1
241         jnz     2f
242         // hit at way 1; swap upwards
243         /* stats only */
244         movabsq $VG_(stats__n_xIndir_hits1_32), %r8
245         addl    $1, (%r8)
246         movq    FCS_g0(%r9), %r10   // r10 = old .guest0
247         movq    FCS_h0(%r9), %r11   // r11 = old .host0
248         movq    FCS_h1(%r9), %r12   // r12 = old .host1
249         movq    %rax, FCS_g0(%r9)   // new .guest0 = guest
250         movq    %r12, FCS_h0(%r9)   // new .host0 = old .host1
251         movq    %r10, FCS_g1(%r9)   // new .guest1 = old .guest0
252         movq    %r11, FCS_h1(%r9)   // new .host1 = old .host0
253         jmp     *%r12               // goto old .host1 a.k.a. new .host0
254         ud2
256 2:      // try way 2
257         cmpq    %rax, FCS_g2(%r9)   // cmp against .guest2
258         jnz     3f
259         // hit at way 2; swap upwards
260         /* stats only */
261         movabsq $VG_(stats__n_xIndir_hits2_32), %r8
262         addl    $1, (%r8)
263         movq    FCS_g1(%r9), %r10
264         movq    FCS_h1(%r9), %r11
265         movq    FCS_h2(%r9), %r12
266         movq    %rax, FCS_g1(%r9)
267         movq    %r12, FCS_h1(%r9)
268         movq    %r10, FCS_g2(%r9)
269         movq    %r11, FCS_h2(%r9)
270         jmp     *%r12
271         ud2
273 3:      // try way 3
274         cmpq    %rax, FCS_g3(%r9)   // cmp against .guest3
275         jnz     4f
276         // hit at way 3; swap upwards
277         /* stats only */
278         movabsq $VG_(stats__n_xIndir_hits3_32), %r8
279         addl    $1, (%r8)
280         movq    FCS_g2(%r9), %r10
281         movq    FCS_h2(%r9), %r11
282         movq    FCS_h3(%r9), %r12
283         movq    %rax, FCS_g2(%r9)
284         movq    %r12, FCS_h2(%r9)
285         movq    %r10, FCS_g3(%r9)
286         movq    %r11, FCS_h3(%r9)
287         jmp     *%r12
288         ud2
290 4:      // fast lookup failed
291         /* stats only */
292         movabsq $VG_(stats__n_xIndir_misses_32), %r8
293         addl    $1, (%r8)
295         movq    $VG_TRC_INNER_FASTMISS, %rax
296         movq    $0, %rdx
297         jmp     postamble
299 /* ------ Assisted jump ------ */
300 .globl VG_(disp_cp_xassisted)
301 VG_(disp_cp_xassisted):
302         /* %rbp contains the TRC */
303         movq    %rbp, %rax
304         movq    $0, %rdx
305         jmp     postamble
307 /* ------ Event check failed ------ */
308 .globl VG_(disp_cp_evcheck_fail)
309 VG_(disp_cp_evcheck_fail):
310         movq    $VG_TRC_INNER_COUNTERZERO, %rax
311         movq    $0, %rdx
312         jmp     postamble
315 #endif // defined(VGP_amd64_darwin)
317 /* Let the linker know we don't need an executable stack */
318 MARK_STACK_NO_EXEC
320 /*--------------------------------------------------------------------*/
321 /*--- end                                                          ---*/
322 /*--------------------------------------------------------------------*/