dispatch-x86-linux.S revision ed07e00d438c74b7a23c01bfffde77e3968305e4
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The core dispatch loop, for jumping to a code address.       ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                         dispatch-x86-linux.S ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of Valgrind, a dynamic binary instrumentation
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  framework.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Copyright (C) 2000-2010 Julian Seward
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     jseward@acm.org
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux)
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics_asm.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_dispatch_asm.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab_asm.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_offsets.h"	/* for OFFSET_x86_EIP */
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- run all translations except no-redir ones.           ---*/
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Preamble (set everything up)                 ---*/
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* signature:
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.text
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.globl VG_(run_innerloop)
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.type  VG_(run_innerloop), @function
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_innerloop):
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* 4(%esp) holds guest_state */
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* 8(%esp) holds do_profiling */
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* ----- entry point to VG_(run_innerloop) ----- */
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	%ebx
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	%ecx
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	%edx
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	%esi
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	%edi
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	%ebp
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* 28(%esp) holds guest_state */
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* 32(%esp) holds do_profiling */
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Set up the guest state pointer */
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	28(%esp), %ebp
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* fetch %EIP into %eax */
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	OFFSET_x86_EIP(%ebp), %eax
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* set host FPU control word to the default mode expected
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           by VEX-generated code.  See comments in libvex.h for
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           more info. */
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	finit
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	$0x027F
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fldcw	(%esp)
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addl	$4, %esp
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* set host SSE control word to the default mode expected
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   by VEX-generated code. */
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	$0, VG_(machine_x86_have_mxcsr)
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jz	L1
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	$0x1F80
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ldmxcsr	(%esp)
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addl	$4, %esp
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownL1:
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* set dir flag to known value */
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cld
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* fall into main loop (the right one) */
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	$0, 32(%esp) /* do_profiling */
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	je	VG_(run_innerloop__dispatch_unprofiled)
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp	VG_(run_innerloop__dispatch_profiled)
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NO-PROFILING (standard) dispatcher           ---*/
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.align	16
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global	VG_(run_innerloop__dispatch_unprofiled)
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_innerloop__dispatch_unprofiled):
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* AT ENTRY: %eax is next guest addr, %ebp is possibly
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           modified guest state ptr */
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Has the guest state pointer been messed with?  If yes, exit. */
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	28(%esp), %ebp
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jnz	gsp_changed
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* save the jump address in the guest state */
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	%eax, OFFSET_x86_EIP(%ebp)
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Are we out of timeslice?  If yes, defer to scheduler. */
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	subl	$1, VG_(dispatch_ctr)
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jz	counter_is_zero
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* try a fast lookup in the translation cache */
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	%eax, %ebx			/* next guest addr */
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	andl	$ VG_TT_FAST_MASK, %ebx		/* entry# */
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	0+VG_(tt_fast)(,%ebx,8), %esi	/* .guest */
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	4+VG_(tt_fast)(,%ebx,8), %edi	/* .host */
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	%eax, %esi
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jnz	fast_lookup_failed
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Found a match.  Jump to .host. */
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp 	*%edi
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ud2	/* persuade insn decoders not to speculate past here */
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* generated code should run, then jump back to
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   VG_(run_innerloop__dispatch_unprofiled). */
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PROFILING dispatcher (can be much slower)    ---*/
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.align	16
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global	VG_(run_innerloop__dispatch_profiled)
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_innerloop__dispatch_profiled):
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* AT ENTRY: %eax is next guest addr, %ebp is possibly
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           modified guest state ptr */
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Has the guest state pointer been messed with?  If yes, exit. */
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	28(%esp), %ebp
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jnz	gsp_changed
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* save the jump address in the guest state */
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	%eax, OFFSET_x86_EIP(%ebp)
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Are we out of timeslice?  If yes, defer to scheduler. */
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	subl	$1, VG_(dispatch_ctr)
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jz	counter_is_zero
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* try a fast lookup in the translation cache */
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	%eax, %ebx			/* next guest addr */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	andl	$ VG_TT_FAST_MASK, %ebx		/* entry# */
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	0+VG_(tt_fast)(,%ebx,8), %esi	/* .guest */
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	4+VG_(tt_fast)(,%ebx,8), %edi	/* .host */
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	%eax, %esi
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jnz	fast_lookup_failed
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* increment bb profile counter */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* note: innocuous as this sounds, it causes a huge amount more
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           stress on D1 and significantly slows everything down. */
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	VG_(tt_fastN)(,%ebx,4), %edx
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Use "addl $1", not "incl", to avoid partial-flags stall on P4 */
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addl	$1, (%edx)
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Found a match.  Jump to .host. */
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp 	*%edi
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ud2	/* persuade insn decoders not to speculate past here */
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* generated code should run, then jump back to
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   VG_(run_innerloop__dispatch_profiled). */
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- exit points                                  ---*/
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browngsp_changed:
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Someone messed with the gsp.  Have to
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           defer to scheduler to resolve this.  dispatch ctr
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   is not yet decremented, so no need to increment. */
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* %EIP is NOT up to date here.  First, need to write
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   %eax back to %EIP, but without trashing %ebp since
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   that holds the value we want to return to the scheduler.
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   Hence use %esi transiently for the guest state pointer. */
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	28(%esp), %esi
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	%eax, OFFSET_x86_EIP(%esi)
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	%ebp, %eax
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp	run_innerloop_exit
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browncounter_is_zero:
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* %EIP is up to date here */
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* back out decrement of the dispatch counter */
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addl	$1, VG_(dispatch_ctr)
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	$ VG_TRC_INNER_COUNTERZERO, %eax
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp	run_innerloop_exit
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfast_lookup_failed:
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* %EIP is up to date here */
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* back out decrement of the dispatch counter */
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addl	$1, VG_(dispatch_ctr)
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	$ VG_TRC_INNER_FASTMISS, %eax
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp	run_innerloop_exit
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All exits from the dispatcher go through here.  %eax holds
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the return value.
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownrun_innerloop_exit:
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* We're leaving.  Check that nobody messed with
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           %mxcsr or %fpucw.  We can't mess with %eax here as it
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   holds the tentative return value, but any other is OK. */
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(ENABLE_INNER)
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* This check fails for self-hosting, so skip in that case */
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	$0
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	fstcw	(%esp)
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	$0x027F, (%esp)
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%esi /* get rid of the word without trashing %eflags */
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jnz	invariant_violation
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	$0, VG_(machine_x86_have_mxcsr)
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jz	L2
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl	$0
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	stmxcsr	(%esp)
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	andl	$0xFFFFFFC0, (%esp)  /* mask out status flags */
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmpl	$0x1F80, (%esp)
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%esi
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jnz	invariant_violation
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownL2:	/* otherwise we're OK */
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp	run_innerloop_exit_REALLY
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninvariant_violation:
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl	$ VG_TRC_INVARIANT_FAILED, %eax
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp	run_innerloop_exit_REALLY
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownrun_innerloop_exit_REALLY:
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%ebp
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%edi
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%esi
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%edx
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%ecx
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl	%ebx
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ret
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.size VG_(run_innerloop), .-VG_(run_innerloop)
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- A special dispatcher, for running no-redir           ---*/
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- translations.  Just runs the given translation once. ---*/
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* signature:
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(run_a_noredir_translation) ( UWord* argblock );
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and 2 to carry results:
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0: input:  ptr to translation
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      1: input:  ptr to guest state
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      2: output: next guest PC
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      3: output: guest state pointer afterwards (== thread return code)
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.align 16
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global VG_(run_a_noredir_translation)
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.type VG_(run_a_noredir_translation), @function
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_a_noredir_translation):
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Save callee-saves regs */
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl %esi
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl %edi
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl %ebp
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pushl %ebx
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl 20(%esp), %edi	/* %edi = argblock */
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl 4(%edi), %ebp	/* argblock[1] */
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	jmp *0(%edi)		/* argblock[0] */
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ud2
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* If the translation has been correctly constructed, we
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	should resume at the the following label. */
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global VG_(run_a_noredir_translation__return_point)
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_a_noredir_translation__return_point):
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl 20(%esp), %edi
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl %eax, 8(%edi)	/* argblock[2] */
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	movl %ebp, 12(%edi)	/* argblock[3] */
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl %ebx
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl %ebp
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl %edi
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	popl %esi
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ret
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.size VG_(run_a_noredir_translation), .-VG_(run_a_noredir_translation)
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let the linker know we don't need an executable stack */
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.section .note.GNU-stack,"",@progbits
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_x86_linux)
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
316