2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address. ---*/
4 /*--- dispatch-x86-linux.S ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2013 Julian Seward
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, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 The GNU General Public License is contained in the file COPYING.
32 #if defined(VGP_x86_linux)
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_x86_EIP */
40 /*------------------------------------------------------------*/
42 /*--- The dispatch loop. VG_(disp_run_translations) is ---*/
43 /*--- used to run all translations, ---*/
44 /*--- including no-redir ones. ---*/
46 /*------------------------------------------------------------*/
48 /*----------------------------------------------------*/
49 /*--- Entry and preamble (set everything up) ---*/
50 /*----------------------------------------------------*/
53 void VG_(disp_run_translations)( UWord* two_words,
58 .globl VG_(disp_run_translations)
59 .type VG_(disp_run_translations), @function
60 VG_(disp_run_translations):
61 /* 0(%esp) holds our return address. */
62 /* 4(%esp) holds two_words */
63 /* 8(%esp) holds guest_state */
64 /* 12(%esp) holds host_addr */
68 /* Save integer registers, since this is a pseudo-function. */
77 /* 28+4(%esp) holds two_words */
78 /* 28+8(%esp) holds guest_state */
79 /* 28+12(%esp) holds host_addr */
81 /* Get the host CPU in the state expected by generated code. */
83 /* set host FPU control word to the default mode expected
84 by VEX-generated code. See comments in libvex.h for
91 /* set host SSE control word to the default mode expected
92 by VEX-generated code. */
93 cmpl $0, VG_(machine_x86_have_mxcsr)
99 /* set dir flag to known value */
102 /* Set up the guest state pointer */
103 movl 28+8(%esp), %ebp
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. */
113 /*----------------------------------------------------*/
114 /*--- Postamble and exit. ---*/
115 /*----------------------------------------------------*/
118 /* At this point, %eax and %edx contain two
119 words to be returned to the caller. %eax
120 holds a TRC value, and %edx optionally may
121 hold another word (for CHAIN_ME exits, the
122 address of the place to patch.) */
124 /* We're leaving. Check that nobody messed with %mxcsr
125 or %fpucw. We can't mess with %eax or %edx here as they
126 holds the tentative return value, but any others are OK. */
127 #if !defined(ENABLE_INNER)
128 /* This check fails for self-hosting, so skip in that case */
132 popl %esi /* get rid of the word without trashing %eflags */
133 jnz invariant_violation
135 # cmpl $0, VG_(machine_x86_have_mxcsr)
139 andl $0xFFFFFFC0, (%esp) /* mask out status flags */
142 jnz invariant_violation
143 L2: /* otherwise we're OK */
146 movl $VG_TRC_INVARIANT_FAILED, %eax
150 /* Stash return values */
151 movl 28+4(%esp), %edi /* two_words */
154 /* Restore int regs and return. */
164 /*----------------------------------------------------*/
165 /*--- Continuation points ---*/
166 /*----------------------------------------------------*/
168 /* ------ Chain me to slow entry point ------ */
169 .global VG_(disp_cp_chain_me_to_slowEP)
170 VG_(disp_cp_chain_me_to_slowEP):
171 /* We got called. The return address indicates
172 where the patching needs to happen. Collect
173 the return address and, exit back to C land,
174 handing the caller the pair (Chain_me_S, RA) */
175 movl $VG_TRC_CHAIN_ME_TO_SLOW_EP, %eax
177 /* 5 = movl $VG_(disp_chain_me_to_slowEP), %edx;
182 /* ------ Chain me to fast entry point ------ */
183 .global VG_(disp_cp_chain_me_to_fastEP)
184 VG_(disp_cp_chain_me_to_fastEP):
185 /* We got called. The return address indicates
186 where the patching needs to happen. Collect
187 the return address and, exit back to C land,
188 handing the caller the pair (Chain_me_F, RA) */
189 movl $VG_TRC_CHAIN_ME_TO_FAST_EP, %eax
191 /* 5 = movl $VG_(disp_chain_me_to_fastEP), %edx;
196 /* ------ Indirect but boring jump ------ */
197 .global VG_(disp_cp_xindir)
199 /* Where are we going? */
200 movl OFFSET_x86_EIP(%ebp), %eax
203 addl $1, VG_(stats__n_xindirs_32)
205 /* try a fast lookup in the translation cache */
206 movl %eax, %ebx /* next guest addr */
207 andl $VG_TT_FAST_MASK, %ebx /* entry# */
208 movl 0+VG_(tt_fast)(,%ebx,8), %esi /* .guest */
209 movl 4+VG_(tt_fast)(,%ebx,8), %edi /* .host */
211 jnz fast_lookup_failed
213 /* Found a match. Jump to .host. */
215 ud2 /* persuade insn decoders not to speculate past here */
219 addl $1, VG_(stats__n_xindir_misses_32)
221 movl $VG_TRC_INNER_FASTMISS, %eax
225 /* ------ Assisted jump ------ */
226 .global VG_(disp_cp_xassisted)
227 VG_(disp_cp_xassisted):
228 /* %ebp contains the TRC */
233 /* ------ Event check failed ------ */
234 .global VG_(disp_cp_evcheck_fail)
235 VG_(disp_cp_evcheck_fail):
236 movl $VG_TRC_INNER_COUNTERZERO, %eax
241 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
243 /* Let the linker know we don't need an executable stack */
244 .section .note.GNU-stack,"",@progbits
246 #endif // defined(VGP_x86_linux)
248 /*--------------------------------------------------------------------*/
250 /*--------------------------------------------------------------------*/