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