Home | History | Annotate | Download | only in m_dispatch
      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-2013 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_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:
     53 void 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
     60 VG_(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 
    119 postamble:
    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
    145 invariant_violation:
    146 	movq	$VG_TRC_INVARIANT_FAILED, %rax
    147         movq    $0, %rdx
    148 
    149 remove_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)
    177 VG_(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)
    191 VG_(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)
    205 VG_(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 
    226 fast_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)
    236 VG_(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)
    244 VG_(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