1
2/*--------------------------------------------------------------------*/
3/*--- The core dispatch loop, for jumping to a code address.       ---*/
4/*---                                       dispatch-amd64-linux.S ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8  This file is part of Valgrind, a dynamic binary instrumentation
9  framework.
10
11  Copyright (C) 2000-2012 Julian Seward
12     jseward@acm.org
13
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.
18
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.
23
24  You should have received a copy of the GNU General Public License
25  along with this program; if not, write to the Free Software
26  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27  02111-1307, USA.
28
29  The GNU General Public License is contained in the file COPYING.
30*/
31
32#if defined(VGP_amd64_linux)
33
34#include "pub_core_basics_asm.h"
35#include "pub_core_dispatch_asm.h"
36#include "pub_core_transtab_asm.h"
37#include "libvex_guest_offsets.h"	/* for OFFSET_amd64_RIP */
38
39
40/*------------------------------------------------------------*/
41/*---                                                      ---*/
42/*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
43/*--- used to run all translations,                        ---*/
44/*--- including no-redir ones.                             ---*/
45/*---                                                      ---*/
46/*------------------------------------------------------------*/
47
48/*----------------------------------------------------*/
49/*--- Entry and preamble (set everything up)       ---*/
50/*----------------------------------------------------*/
51
52/* signature:
53void VG_(disp_run_translations)( UWord* two_words,
54                                 void*  guest_state,
55                                 Addr   host_addr );
56*/
57.text
58.globl VG_(disp_run_translations)
59.type  VG_(disp_run_translations), @function
60VG_(disp_run_translations):
61        /* %rdi holds two_words    */
62	/* %rsi holds guest_state  */
63	/* %rdx holds host_addr    */
64
65        /* The preamble */
66
67        /* Save integer registers, since this is a pseudo-function. */
68        pushq   %rax
69	pushq	%rbx
70	pushq	%rcx
71        pushq   %rdx
72	pushq	%rsi
73	pushq	%rbp
74	pushq	%r8
75	pushq	%r9
76	pushq	%r10
77	pushq	%r11
78	pushq	%r12
79	pushq	%r13
80	pushq	%r14
81	pushq	%r15
82        /* %rdi must be saved last */
83	pushq	%rdi
84
85        /* Get the host CPU in the state expected by generated code. */
86
87	/* set host FPU control word to the default mode expected
88           by VEX-generated code.  See comments in libvex.h for
89           more info. */
90	finit
91	pushq	$0x027F
92	fldcw	(%rsp)
93	addq	$8, %rsp
94
95	/* set host SSE control word to the default mode expected
96	   by VEX-generated code. */
97	pushq	$0x1F80
98	ldmxcsr	(%rsp)
99	addq	$8, %rsp
100
101	/* set dir flag to known value */
102	cld
103
104	/* Set up the guest state pointer */
105	movq	%rsi, %rbp
106
107        /* and jump into the code cache.  Chained translations in
108           the code cache run, until for whatever reason, they can't
109           continue.  When that happens, the translation in question
110           will jump (or call) to one of the continuation points
111           VG_(cp_...) below. */
112        jmpq    *%rdx
113       	/*NOTREACHED*/
114
115/*----------------------------------------------------*/
116/*--- Postamble and exit.                          ---*/
117/*----------------------------------------------------*/
118
119postamble:
120        /* At this point, %rax and %rdx contain two
121           words to be returned to the caller.  %rax
122           holds a TRC value, and %rdx optionally may
123           hold another word (for CHAIN_ME exits, the
124           address of the place to patch.) */
125
126	/* We're leaving.  Check that nobody messed with %mxcsr
127           or %fpucw.  We can't mess with %rax or %rdx here as they
128           hold the tentative return values, but any others are OK. */
129#if !defined(ENABLE_INNER)
130        /* This check fails for self-hosting, so skip in that case */
131	pushq	$0
132	fstcw	(%rsp)
133	cmpl	$0x027F, (%rsp)
134	popq	%r15 /* get rid of the word without trashing %rflags */
135	jnz	invariant_violation
136#endif
137	pushq	$0
138	stmxcsr	(%rsp)
139	andl	$0xFFFFFFC0, (%rsp)  /* mask out status flags */
140	cmpl	$0x1F80, (%rsp)
141	popq	%r15
142	jnz	invariant_violation
143	/* otherwise we're OK */
144	jmp	remove_frame
145invariant_violation:
146	movq	$VG_TRC_INVARIANT_FAILED, %rax
147        movq    $0, %rdx
148
149remove_frame:
150        /* Pop %rdi, stash return values */
151	popq	%rdi
152        movq    %rax, 0(%rdi)
153        movq    %rdx, 8(%rdi)
154        /* Now pop everything else */
155	popq	%r15
156	popq	%r14
157	popq	%r13
158	popq	%r12
159	popq	%r11
160	popq	%r10
161	popq	%r9
162	popq	%r8
163	popq	%rbp
164	popq	%rsi
165	popq	%rdx
166	popq	%rcx
167	popq	%rbx
168	popq	%rax
169	ret
170
171/*----------------------------------------------------*/
172/*--- Continuation points                          ---*/
173/*----------------------------------------------------*/
174
175/* ------ Chain me to slow entry point ------ */
176.global VG_(disp_cp_chain_me_to_slowEP)
177VG_(disp_cp_chain_me_to_slowEP):
178        /* We got called.  The return address indicates
179           where the patching needs to happen.  Collect
180           the return address and, exit back to C land,
181           handing the caller the pair (Chain_me_S, RA) */
182        movq    $VG_TRC_CHAIN_ME_TO_SLOW_EP, %rax
183        popq    %rdx
184        /* 10 = movabsq $VG_(disp_chain_me_to_slowEP), %r11;
185           3  = call *%r11 */
186        subq    $10+3, %rdx
187        jmp     postamble
188
189/* ------ Chain me to fast entry point ------ */
190.global VG_(disp_cp_chain_me_to_fastEP)
191VG_(disp_cp_chain_me_to_fastEP):
192        /* We got called.  The return address indicates
193           where the patching needs to happen.  Collect
194           the return address and, exit back to C land,
195           handing the caller the pair (Chain_me_F, RA) */
196        movq    $VG_TRC_CHAIN_ME_TO_FAST_EP, %rax
197        popq    %rdx
198        /* 10 = movabsq $VG_(disp_chain_me_to_fastEP), %r11;
199           3  = call *%r11 */
200        subq    $10+3, %rdx
201        jmp     postamble
202
203/* ------ Indirect but boring jump ------ */
204.global VG_(disp_cp_xindir)
205VG_(disp_cp_xindir):
206	/* Where are we going? */
207	movq	OFFSET_amd64_RIP(%rbp), %rax
208
209        /* stats only */
210        addl    $1, VG_(stats__n_xindirs_32)
211
212	/* try a fast lookup in the translation cache */
213	movabsq $VG_(tt_fast), %rcx
214	movq	%rax, %rbx		/* next guest addr */
215	andq	$VG_TT_FAST_MASK, %rbx	/* entry# */
216	shlq	$4, %rbx		/* entry# * sizeof(FastCacheEntry) */
217	movq	0(%rcx,%rbx,1), %r10	/* .guest */
218	movq	8(%rcx,%rbx,1), %r11	/* .host */
219	cmpq	%rax, %r10
220	jnz	fast_lookup_failed
221
222        /* Found a match.  Jump to .host. */
223	jmp 	*%r11
224	ud2	/* persuade insn decoders not to speculate past here */
225
226fast_lookup_failed:
227        /* stats only */
228        addl    $1, VG_(stats__n_xindir_misses_32)
229
230	movq	$VG_TRC_INNER_FASTMISS, %rax
231        movq    $0, %rdx
232	jmp	postamble
233
234/* ------ Assisted jump ------ */
235.global VG_(disp_cp_xassisted)
236VG_(disp_cp_xassisted):
237        /* %rbp contains the TRC */
238        movq    %rbp, %rax
239        movq    $0, %rdx
240        jmp     postamble
241
242/* ------ Event check failed ------ */
243.global VG_(disp_cp_evcheck_fail)
244VG_(disp_cp_evcheck_fail):
245       	movq	$VG_TRC_INNER_COUNTERZERO, %rax
246        movq    $0, %rdx
247	jmp	postamble
248
249
250.size VG_(disp_run_translations), .-VG_(disp_run_translations)
251
252/* Let the linker know we don't need an executable stack */
253.section .note.GNU-stack,"",@progbits
254
255#endif // defined(VGP_amd64_linux)
256
257/*--------------------------------------------------------------------*/
258/*--- end                                                          ---*/
259/*--------------------------------------------------------------------*/
260