• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2/*--------------------------------------------------------------------*/
3/*--- The core dispatch loop, for jumping to a code address.       ---*/
4/*---                                        dispatch-x86-darwin.S ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8  This file is part of Valgrind, a dynamic binary instrumentation
9  framework.
10
11  Copyright (C) 2000-2006 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_x86_darwin)
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_x86_EIP */
38
39
40/* Global variables */
41/* These are defined here instead of in their respective C files to
42   avoid extra PIC branch code here. */
43.data
44.align 2
45
46/* m_transtab.c */
47.globl VG_(tt_fast)
48.align 4
49VG_(tt_fast):	.space VG_TT_FAST_SIZE*8, 0  /* (2*Addr) [VG_TT_FAST_SIZE] */
50.globl VG_(tt_fastN)
51VG_(tt_fastN):	.space VG_TT_FAST_SIZE*4, 0  /* (UInt *) [VG_TT_FAST_SIZE] */
52
53/* scheduler.c */
54.globl VG_(dispatch_ctr)
55VG_(dispatch_ctr):	.long 0
56
57
58/*------------------------------------------------------------*/
59/*---                                                      ---*/
60/*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
61/*--- run all translations except no-redir ones.           ---*/
62/*---                                                      ---*/
63/*------------------------------------------------------------*/
64
65/*----------------------------------------------------*/
66/*--- Preamble (set everything up)                 ---*/
67/*----------------------------------------------------*/
68
69/* signature:
70UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
71*/
72.text
73.globl VG_(run_innerloop)
74VG_(run_innerloop):
75	/* 4(%esp) holds guest_state */
76	/* 8(%esp) holds do_profiling */
77
78	/* ----- entry point to VG_(run_innerloop) ----- */
79	pushl	%ebx
80	pushl	%ecx
81	pushl	%edx
82	pushl	%esi
83	pushl	%edi
84	pushl	%ebp
85
86	/* 28(%esp) holds guest_state */
87	/* 32(%esp) holds do_profiling */
88
89	/* Set up the guest state pointer */
90	movl	28(%esp), %ebp
91
92	/* fetch %EIP into %eax */
93	movl	OFFSET_x86_EIP(%ebp), %eax
94
95	/* set host FPU control word to the default mode expected
96           by VEX-generated code.  See comments in libvex.h for
97           more info. */
98	finit
99	pushl	$0x027F
100	fldcw	(%esp)
101	addl	$4, %esp
102
103	/* set host SSE control word to the default mode expected
104	   by VEX-generated code. */
105	cmpl	$0, VG_(machine_x86_have_mxcsr)
106	jz	L1
107	pushl	$0x1F80
108	ldmxcsr	(%esp)
109	addl	$4, %esp
110L1:
111	/* set dir flag to known value */
112	cld
113
114	/* fall into main loop (the right one) */
115	cmpl	$0, 32(%esp) /* do_profiling */
116	je	VG_(run_innerloop__dispatch_unprofiled)
117	jmp	VG_(run_innerloop__dispatch_profiled)
118	/*NOTREACHED*/
119
120/*----------------------------------------------------*/
121/*--- NO-PROFILING (standard) dispatcher           ---*/
122/*----------------------------------------------------*/
123
124.globl	VG_(run_innerloop__dispatch_unprofiled)
125VG_(run_innerloop__dispatch_unprofiled):
126	/* AT ENTRY: %eax is next guest addr, %ebp is possibly
127           modified guest state ptr */
128
129	/* Has the guest state pointer been messed with?  If yes, exit. */
130	cmpl	28(%esp), %ebp
131	jnz	gsp_changed
132
133	/* save the jump address in the guest state */
134	movl	%eax, OFFSET_x86_EIP(%ebp)
135
136	/* Are we out of timeslice?  If yes, defer to scheduler. */
137	subl	$1, VG_(dispatch_ctr)
138	jz	counter_is_zero
139
140	/* try a fast lookup in the translation cache */
141	movl	%eax, %ebx
142	andl	$VG_TT_FAST_MASK, %ebx
143	movl	0+VG_(tt_fast)(,%ebx,8), %esi	/* .guest */
144	movl	4+VG_(tt_fast)(,%ebx,8), %edi	/* .host */
145	cmpl	%eax, %esi
146	jnz	fast_lookup_failed
147
148	/* Found a match.  Jump to .host. */
149	jmp 	*%edi
150	ud2	/* persuade insn decoders not to speculate past here */
151	/* generated code should run, then jump back to
152	   VG_(run_innerloop__dispatch_unprofiled). */
153	/*NOTREACHED*/
154
155/*----------------------------------------------------*/
156/*--- PROFILING dispatcher (can be much slower)    ---*/
157/*----------------------------------------------------*/
158
159.globl	VG_(run_innerloop__dispatch_profiled)
160VG_(run_innerloop__dispatch_profiled):
161	/* AT ENTRY: %eax is next guest addr, %ebp is possibly
162           modified guest state ptr */
163
164	/* Has the guest state pointer been messed with?  If yes, exit. */
165	cmpl	28(%esp), %ebp
166	jnz	gsp_changed
167
168	/* save the jump address in the guest state */
169	movl	%eax, OFFSET_x86_EIP(%ebp)
170
171	/* Are we out of timeslice?  If yes, defer to scheduler. */
172	subl	$1, VG_(dispatch_ctr)
173	jz	counter_is_zero
174
175	/* try a fast lookup in the translation cache */
176	movl	%eax, %ebx
177	andl	$VG_TT_FAST_MASK, %ebx
178	movl	0+VG_(tt_fast)(,%ebx,8), %esi	/* .guest */
179	movl	4+VG_(tt_fast)(,%ebx,8), %edi	/* .host */
180	cmpl	%eax, %esi
181	jnz	fast_lookup_failed
182	/* increment bb profile counter */
183	/* note: innocuous as this sounds, it causes a huge amount more
184           stress on D1 and significantly slows everything down. */
185	movl	VG_(tt_fastN)(,%ebx,4), %edx
186	/* Use "addl $1", not "incl", to avoid partial-flags stall on P4 */
187	addl	$1, (%edx)
188
189	/* Found a match.  Jump to .host. */
190	jmp 	*%edi
191	ud2	/* persuade insn decoders not to speculate past here */
192	/* generated code should run, then jump back to
193	   VG_(run_innerloop__dispatch_profiled). */
194	/*NOTREACHED*/
195
196/*----------------------------------------------------*/
197/*--- exit points                                  ---*/
198/*----------------------------------------------------*/
199
200gsp_changed:
201	/* Someone messed with the gsp.  Have to
202           defer to scheduler to resolve this.  dispatch ctr
203	   is not yet decremented, so no need to increment. */
204	/* %EIP is NOT up to date here.  First, need to write
205	   %eax back to %EIP, but without trashing %ebp since
206	   that holds the value we want to return to the scheduler.
207	   Hence use %esi transiently for the guest state pointer. */
208	movl	28(%esp), %esi
209	movl	%eax, OFFSET_x86_EIP(%esi)
210	movl	%ebp, %eax
211	jmp	run_innerloop_exit
212	/*NOTREACHED*/
213
214counter_is_zero:
215	/* %EIP is up to date here */
216	/* back out decrement of the dispatch counter */
217	addl	$1, VG_(dispatch_ctr)
218	movl	$VG_TRC_INNER_COUNTERZERO, %eax
219	jmp	run_innerloop_exit
220	/*NOTREACHED*/
221
222fast_lookup_failed:
223	/* %EIP is up to date here */
224	/* back out decrement of the dispatch counter */
225	addl	$1, VG_(dispatch_ctr)
226	movl	$VG_TRC_INNER_FASTMISS, %eax
227	jmp	run_innerloop_exit
228	/*NOTREACHED*/
229
230
231
232/* All exits from the dispatcher go through here.  %eax holds
233   the return value.
234*/
235run_innerloop_exit:
236	/* We're leaving.  Check that nobody messed with
237           %mxcsr or %fpucw.  We can't mess with %eax here as it
238	   holds the tentative return value, but any other is OK. */
239#if !defined(ENABLE_INNER)
240        /* This check fails for self-hosting, so skip in that case */
241	pushl	$0
242	fstcw	(%esp)
243	cmpl	$0x027F, (%esp)
244	popl	%esi /* get rid of the word without trashing %eflags */
245	jnz	invariant_violation
246#endif
247	cmpl	$0, VG_(machine_x86_have_mxcsr)
248	jz	L2
249	pushl	$0
250	stmxcsr	(%esp)
251	andl	$0xFFFFFFC0, (%esp)  /* mask out status flags */
252	cmpl	$0x1F80, (%esp)
253	popl	%esi
254	jnz	invariant_violation
255L2:	/* otherwise we're OK */
256	jmp	run_innerloop_exit_REALLY
257
258invariant_violation:
259	movl	$VG_TRC_INVARIANT_FAILED, %eax
260	jmp	run_innerloop_exit_REALLY
261
262run_innerloop_exit_REALLY:
263	popl	%ebp
264	popl	%edi
265	popl	%esi
266	popl	%edx
267	popl	%ecx
268	popl	%ebx
269	ret
270
271
272/*------------------------------------------------------------*/
273/*---                                                      ---*/
274/*--- A special dispatcher, for running no-redir           ---*/
275/*--- translations.  Just runs the given translation once. ---*/
276/*---                                                      ---*/
277/*------------------------------------------------------------*/
278
279/* signature:
280void VG_(run_a_noredir_translation) ( UWord* argblock );
281*/
282
283/* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
284   and 2 to carry results:
285      0: input:  ptr to translation
286      1: input:  ptr to guest state
287      2: output: next guest PC
288      3: output: guest state pointer afterwards (== thread return code)
289*/
290.globl VG_(run_a_noredir_translation)
291VG_(run_a_noredir_translation):
292	/* Save callee-saves regs */
293	pushl %esi
294	pushl %edi
295	pushl %ebp
296	pushl %ebx
297
298	movl 20(%esp), %edi	/* %edi = argblock */
299	movl 4(%edi), %ebp	/* argblock[1] */
300	jmp *0(%edi)		/* argblock[0] */
301	/*NOTREACHED*/
302	ud2
303	/* If the translation has been correctly constructed, we
304	should resume at the the following label. */
305.globl VG_(run_a_noredir_translation__return_point)
306VG_(run_a_noredir_translation__return_point):
307	movl 20(%esp), %edi
308	movl %eax, 8(%edi)	/* argblock[2] */
309	movl %ebp, 12(%edi)	/* argblock[3] */
310
311	popl %ebx
312	popl %ebp
313	popl %edi
314	popl %esi
315	ret
316
317#endif // defined(VGP_x86_darwin)
318
319/*--------------------------------------------------------------------*/
320/*--- end                                                          ---*/
321/*--------------------------------------------------------------------*/
322