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