]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
(post-tchain-merge cleanup): un-break the build on OSX by fixing up
authorJulian Seward <jseward@acm.org>
Sat, 21 Apr 2012 13:55:28 +0000 (13:55 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 21 Apr 2012 13:55:28 +0000 (13:55 +0000)
the dispatcher code accordingly.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12522

coregrind/m_dispatch/dispatch-amd64-darwin.S
coregrind/m_dispatch/dispatch-x86-darwin.S

index 63542810d9836d21c364292b587f9feddc2f39dd..0180fc17d644f908fd6c045029a23615d9993846 100644 (file)
 
 /*------------------------------------------------------------*/
 /*---                                                      ---*/
-/*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
-/*--- run all translations except no-redir ones.           ---*/
+/*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
+/*--- used to run all translations,                        ---*/
+/*--- including no-redir ones.                             ---*/
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
 /*----------------------------------------------------*/
-/*--- Preamble (set everything up)                 ---*/
+/*--- Entry and preamble (set everything up)       ---*/
 /*----------------------------------------------------*/
 
 /* signature:
-UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
+void VG_(disp_run_translations)( UWord* two_words,
+                                 void*  guest_state, 
+                                 Addr   host_addr );
 */
-
 .text
-.globl VG_(run_innerloop)
-VG_(run_innerloop):
-       /* %rdi holds guest_state */
-       /* %rsi holds do_profiling */
-       
-       /* ----- entry point to VG_(run_innerloop) ----- */
+.globl VG_(disp_run_translations)
+VG_(disp_run_translations):
+        /* %rdi holds two_words    */
+       /* %rsi holds guest_state  */
+       /* %rdx holds host_addr    */
+
+        /* The preamble */
+
+        /* Save integer registers, since this is a pseudo-function. */
+        pushq   %rax
        pushq   %rbx
        pushq   %rcx
-       pushq   %rdx
+        pushq   %rdx
        pushq   %rsi
        pushq   %rbp
        pushq   %r8
@@ -72,20 +78,10 @@ VG_(run_innerloop):
        pushq   %r13
        pushq   %r14
        pushq   %r15
-       pushq   %rdi  /* guest_state */
-
-       movq    VG_(dispatch_ctr)@GOTPCREL(%rip), %r15
-       movl    (%r15), %r15d
-       pushq   %r15
+        /* %rdi must be saved last */
+       pushq   %rdi
 
-       /* 8(%rsp) holds cached copy of guest_state ptr */
-       /* 0(%rsp) holds cached copy of VG_(dispatch_ctr) */
-
-       /* Set up the guest state pointer */
-       movq    %rdi, %rbp
-       
-       /* fetch %RIP into %rax */
-       movq    OFFSET_amd64_RIP(%rbp), %rax
+        /* Get the host CPU in the state expected by generated code. */
 
        /* set host FPU control word to the default mode expected 
            by VEX-generated code.  See comments in libvex.h for
@@ -104,153 +100,37 @@ VG_(run_innerloop):
        /* set dir flag to known value */
        cld
 
-       /* fall into main loop  (the right one) */
-       cmpq    $0, %rsi
-       je      VG_(run_innerloop__dispatch_unassisted_unprofiled)
-       jmp     VG_(run_innerloop__dispatch_unassisted_profiled)
-       /*NOTREACHED*/  
-
-/*----------------------------------------------------*/
-/*--- NO-PROFILING (standard) dispatcher           ---*/
-/*----------------------------------------------------*/
-
-.align 4
-.globl VG_(run_innerloop__dispatch_unassisted_unprofiled)
-VG_(run_innerloop__dispatch_unassisted_unprofiled):
-       /* AT ENTRY: %rax is next guest addr, %rbp is the
-           unmodified guest state ptr */
-
-       /* save the jump address in the guest state */
-       movq    %rax, OFFSET_amd64_RIP(%rbp)
-
-       /* Are we out of timeslice?  If yes, defer to scheduler. */
-       subl    $1, 0(%rsp)
-       jz      counter_is_zero
-
-       /* try a fast lookup in the translation cache */
-       movabsq $VG_(tt_fast), %rcx
-       movq    %rax, %rbx
-       andq    $VG_TT_FAST_MASK, %rbx  /* entry# */
-       shlq    $4, %rbx                /* entry# * sizeof(FastCacheEntry) */
-       movq    0(%rcx,%rbx,1), %r10    /* .guest */
-       movq    8(%rcx,%rbx,1), %r11    /* .host */
-       cmpq    %rax, %r10
-       jnz     fast_lookup_failed
-
-        /* Found a match.  Jump to .host. */
-       jmp     *%r11
-       ud2     /* persuade insn decoders not to speculate past here */
-       /* generated code should run, then jump back to
-          VG_(run_innerloop__dispatch_{un,}assisted_unprofiled). */
-       /*NOTREACHED*/
-
-.align 4
-.globl VG_(run_innerloop__dispatch_assisted_unprofiled)
-VG_(run_innerloop__dispatch_assisted_unprofiled):
-       /* AT ENTRY: %rax is next guest addr, %rbp is the
-           modified guest state ptr.  Since the GSP has changed,
-           jump directly to gsp_changed. */
-        jmp     gsp_changed
-        ud2
-        /*NOTREACHED*/
-
-/*----------------------------------------------------*/
-/*--- PROFILING dispatcher (can be much slower)    ---*/
-/*----------------------------------------------------*/
-
-.align 4
-.globl VG_(run_innerloop__dispatch_unassisted_profiled)
-VG_(run_innerloop__dispatch_unassisted_profiled):
-       /* AT ENTRY: %rax is next guest addr, %rbp is the
-           unmodified guest state ptr */
-
-       /* save the jump address in the guest state */
-       movq    %rax, OFFSET_amd64_RIP(%rbp)
-
-       /* Are we out of timeslice?  If yes, defer to scheduler. */
-       subl    $1, 0(%rsp)
-       jz      counter_is_zero
-
-       /* try a fast lookup in the translation cache */
-        movabsq $VG_(tt_fast), %rcx
-       movq    %rax, %rbx
-       andq    $VG_TT_FAST_MASK, %rbx  /* entry# */
-       shlq    $4, %rbx                /* entry# * sizeof(FastCacheEntry) */
-       movq    0(%rcx,%rbx,1), %r10    /* .guest */
-       movq    8(%rcx,%rbx,1), %r11    /* .host */
-       cmpq    %rax, %r10
-       jnz     fast_lookup_failed
-
-       /* increment bb profile counter */
-       movabsq $VG_(tt_fastN), %rdx
-       shrq    $1, %rbx                /* entry# * sizeof(UInt*) */
-       movq    (%rdx,%rbx,1), %rdx
-       addl    $1, (%rdx)
+       /* Set up the guest state pointer */
+       movq    %rsi, %rbp
 
-        /* Found a match.  Jump to .host. */
-       jmp     *%r11
-       ud2     /* persuade insn decoders not to speculate past here */
-       /* generated code should run, then jump back to
-          VG_(run_innerloop__dispatch_{un,}assisted_profiled). */
-       /*NOTREACHED*/
-
-.align 4
-.globl VG_(run_innerloop__dispatch_assisted_profiled)
-VG_(run_innerloop__dispatch_assisted_profiled):
-       /* AT ENTRY: %rax is next guest addr, %rbp is the
-           modified guest state ptr.  Since the GSP has changed,
-           jump directly to gsp_changed. */
-        jmp     gsp_changed
-        ud2
-        /*NOTREACHED*/
+        /* and jump into the code cache.  Chained translations in
+           the code cache run, until for whatever reason, they can't
+           continue.  When that happens, the translation in question
+           will jump (or call) to one of the continuation points
+           VG_(cp_...) below. */
+        jmpq    *%rdx
+               /*NOTREACHED*/  
 
 /*----------------------------------------------------*/
-/*--- exit points                                  ---*/
+/*--- Postamble and exit.                          ---*/
 /*----------------------------------------------------*/
 
-gsp_changed:
-       /* Someone messed with the gsp.  Have to
-           defer to scheduler to resolve this.  dispatch ctr
-          is not yet decremented, so no need to increment. */
-       /* %RIP is NOT up to date here.  First, need to write
-          %rax back to %RIP, but without trashing %rbp since
-          that holds the value we want to return to the scheduler.
-          Hence use %r15 transiently for the guest state pointer. */
-       movq    8(%rsp), %r15
-       movq    %rax, OFFSET_amd64_RIP(%r15)
-       movq    %rbp, %rax
-       jmp     run_innerloop_exit
-       /*NOTREACHED*/
-
-counter_is_zero:
-       /* %RIP is up to date here */
-       /* back out decrement of the dispatch counter */
-       addl    $1, 0(%rsp)
-       movq    $VG_TRC_INNER_COUNTERZERO, %rax
-       jmp     run_innerloop_exit
-
-fast_lookup_failed:
-       /* %RIP is up to date here */
-       /* back out decrement of the dispatch counter */
-       addl    $1, 0(%rsp)
-       movq    $VG_TRC_INNER_FASTMISS, %rax
-       jmp     run_innerloop_exit
-
-
-
-/* All exits from the dispatcher go through here.  %rax holds
-   the return value. 
-*/
-run_innerloop_exit: 
-       /* We're leaving.  Check that nobody messed with
-           %mxcsr or %fpucw.  We can't mess with %rax here as it
-          holds the tentative return value, but any other is OK. */
+postamble:
+        /* At this point, %rax and %rdx contain two
+           words to be returned to the caller.  %rax
+           holds a TRC value, and %rdx optionally may
+           hold another word (for CHAIN_ME exits, the
+           address of the place to patch.) */
+        
+       /* We're leaving.  Check that nobody messed with %mxcsr
+           or %fpucw.  We can't mess with %rax or %rdx here as they
+           hold the tentative return values, but any others are OK. */
 #if !defined(ENABLE_INNER)
         /* This check fails for self-hosting, so skip in that case */
        pushq   $0
        fstcw   (%rsp)
        cmpl    $0x027F, (%rsp)
-       popq    %r15 /* get rid of the word without trashing %eflags */
+       popq    %r15 /* get rid of the word without trashing %rflags */
        jnz     invariant_violation
 #endif
        pushq   $0
@@ -260,20 +140,17 @@ run_innerloop_exit:
        popq    %r15
        jnz     invariant_violation
        /* otherwise we're OK */
-       jmp     run_innerloop_exit_REALLY
-
+       jmp     remove_frame
 invariant_violation:
        movq    $VG_TRC_INVARIANT_FAILED, %rax
-       jmp     run_innerloop_exit_REALLY
-
-run_innerloop_exit_REALLY:
-
-       /* restore VG_(dispatch_ctr) */ 
-       popq    %r14
-       movq    VG_(dispatch_ctr)@GOTPCREL(%rip), %r15
-       movl    %r14d, (%r15)
+        movq    $0, %rdx
 
+remove_frame:
+        /* Pop %rdi, stash return values */
        popq    %rdi
+        movq    %rax, 0(%rdi)
+        movq    %rdx, 8(%rdi)
+        /* Now pop everything else */
        popq    %r15
        popq    %r14
        popq    %r13
@@ -287,58 +164,89 @@ run_innerloop_exit_REALLY:
        popq    %rdx
        popq    %rcx
        popq    %rbx
+       popq    %rax
        ret     
+        
+/*----------------------------------------------------*/
+/*--- Continuation points                          ---*/
+/*----------------------------------------------------*/
 
-       
-/*------------------------------------------------------------*/
-/*---                                                      ---*/
-/*--- A special dispatcher, for running no-redir           ---*/
-/*--- translations.  Just runs the given translation once. ---*/
-/*---                                                      ---*/
-/*------------------------------------------------------------*/
+/* ------ Chain me to slow entry point ------ */
+.globl VG_(disp_cp_chain_me_to_slowEP)
+VG_(disp_cp_chain_me_to_slowEP):
+        /* We got called.  The return address indicates
+           where the patching needs to happen.  Collect
+           the return address and, exit back to C land,
+           handing the caller the pair (Chain_me_S, RA) */
+        movq    $VG_TRC_CHAIN_ME_TO_SLOW_EP, %rax
+        popq    %rdx
+        /* 10 = movabsq $VG_(disp_chain_me_to_slowEP), %r11;
+           3  = call *%r11 */
+        subq    $10+3, %rdx
+        jmp     postamble
+
+/* ------ Chain me to fast entry point ------ */
+.globl VG_(disp_cp_chain_me_to_fastEP)
+VG_(disp_cp_chain_me_to_fastEP):
+        /* We got called.  The return address indicates
+           where the patching needs to happen.  Collect
+           the return address and, exit back to C land,
+           handing the caller the pair (Chain_me_F, RA) */
+        movq    $VG_TRC_CHAIN_ME_TO_FAST_EP, %rax
+        popq    %rdx
+        /* 10 = movabsq $VG_(disp_chain_me_to_fastEP), %r11;
+           3  = call *%r11 */
+        subq    $10+3, %rdx
+        jmp     postamble
+
+/* ------ Indirect but boring jump ------ */
+.globl VG_(disp_cp_xindir)
+VG_(disp_cp_xindir):
+       /* Where are we going? */
+       movq    OFFSET_amd64_RIP(%rbp), %rax
 
-/* signature:
-void VG_(run_a_noredir_translation) ( UWord* argblock );
-*/
+        /* RM ME -- stats only */
+        movabsq $_vgPlain_stats__n_xindirs, %r10
+        addq    $1, (%r10)
+        
+       /* try a fast lookup in the translation cache */
+       movabsq $VG_(tt_fast), %rcx
+       movq    %rax, %rbx              /* next guest addr */
+       andq    $VG_TT_FAST_MASK, %rbx  /* entry# */
+       shlq    $4, %rbx                /* entry# * sizeof(FastCacheEntry) */
+       movq    0(%rcx,%rbx,1), %r10    /* .guest */
+       movq    8(%rcx,%rbx,1), %r11    /* .host */
+       cmpq    %rax, %r10
+       jnz     fast_lookup_failed
+
+        /* Found a match.  Jump to .host. */
+       jmp     *%r11
+       ud2     /* persuade insn decoders not to speculate past here */
+
+fast_lookup_failed:
+        /* RM ME -- stats only */
+        movabsq $_vgPlain_stats__n_xindir_misses, %r10
+        addq    $1, %r10
+
+       movq    $VG_TRC_INNER_FASTMISS, %rax
+        movq    $0, %rdx
+       jmp     postamble
+
+/* ------ Assisted jump ------ */
+.globl VG_(disp_cp_xassisted)
+VG_(disp_cp_xassisted):
+        /* %rbp contains the TRC */
+        movq    %rbp, %rax
+        movq    $0, %rdx
+        jmp     postamble
+
+/* ------ Event check failed ------ */
+.globl VG_(disp_cp_evcheck_fail)
+VG_(disp_cp_evcheck_fail):
+               movq    $VG_TRC_INNER_COUNTERZERO, %rax
+        movq    $0, %rdx
+       jmp     postamble
 
-/* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
-   and 2 to carry results:
-      0: input:  ptr to translation
-      1: input:  ptr to guest state
-      2: output: next guest PC
-      3: output: guest state pointer afterwards (== thread return code)
-*/
-.align 4
-.globl VG_(run_a_noredir_translation)
-VG_(run_a_noredir_translation):
-       /* Save callee-saves regs */
-       pushq %rbx
-       pushq %rbp
-       pushq %r12
-       pushq %r13
-       pushq %r14
-       pushq %r15
-
-       pushq %rdi  /* we will need it after running the translation */
-       movq 8(%rdi), %rbp
-       jmp *0(%rdi)
-       /*NOTREACHED*/
-       ud2
-       /* If the translation has been correctly constructed, we
-       should resume at the the following label. */
-.globl VG_(run_a_noredir_translation__return_point)
-VG_(run_a_noredir_translation__return_point):
-       popq %rdi
-       movq %rax, 16(%rdi)
-       movq %rbp, 24(%rdi)
-
-       popq  %r15
-       popq  %r14
-       popq  %r13
-       popq  %r12
-       popq  %rbp
-       popq  %rbx
-       ret
 
 #endif // defined(VGP_amd64_darwin)
 
index 1b216b32d91df2f7230aafa3fde5d87b4648ff9c..275d6890c7b7e0c056a8e11d0c661ccc0fbddc56 100644 (file)
 #include "libvex_guest_offsets.h"      /* for OFFSET_x86_EIP */
 
 
-/* Global variables */
-/* These are defined here instead of in their respective C files to
-   avoid extra PIC branch code here. */
-.data
-.align 2
-
-/* m_transtab.c */
-.globl VG_(tt_fast)
-.align 4
-VG_(tt_fast):  .space VG_TT_FAST_SIZE*8, 0  /* (2*Addr) [VG_TT_FAST_SIZE] */
-.globl VG_(tt_fastN)
-VG_(tt_fastN): .space VG_TT_FAST_SIZE*4, 0  /* (UInt *) [VG_TT_FAST_SIZE] */
-
-/* scheduler.c */
-.globl VG_(dispatch_ctr)
-VG_(dispatch_ctr):     .long 0
-
-       
 /*------------------------------------------------------------*/
 /*---                                                      ---*/
-/*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
-/*--- run all translations except no-redir ones.           ---*/
+/*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
+/*--- used to run all translations,                        ---*/
+/*--- including no-redir ones.                             ---*/
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
 /*----------------------------------------------------*/
-/*--- Preamble (set everything up)                 ---*/
+/*--- Entry and preamble (set everything up)       ---*/
 /*----------------------------------------------------*/
 
 /* signature:
-UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
+void VG_(disp_run_translations)( UWord* two_words,
+                                 void*  guest_state, 
+                                 Addr   host_addr );
 */
 .text
-.globl VG_(run_innerloop)
-VG_(run_innerloop):
-       /* 4(%esp) holds guest_state */
-       /* 8(%esp) holds do_profiling */
-       
-       /* ----- entry point to VG_(run_innerloop) ----- */
+.globl VG_(disp_run_translations)
+VG_(disp_run_translations):
+        /* 0(%esp) holds our return address. */
+       /* 4(%esp) holds two_words */
+       /* 8(%esp) holds guest_state */
+       /* 12(%esp) holds host_addr */
+
+        /* The preamble */
+
+        /* Save integer registers, since this is a pseudo-function. */
+        pushl   %eax
        pushl   %ebx
        pushl   %ecx
        pushl   %edx
@@ -83,14 +73,11 @@ VG_(run_innerloop):
        pushl   %edi
        pushl   %ebp
        
-       /* 28(%esp) holds guest_state */
-       /* 32(%esp) holds do_profiling */
+       /* 28+4(%esp) holds two_words */
+       /* 28+8(%esp) holds guest_state */
+       /* 28+12(%esp) holds host_addr */
 
-       /* Set up the guest state pointer */
-       movl    28(%esp), %ebp
-       
-       /* fetch %EIP into %eax */
-       movl    OFFSET_x86_EIP(%ebp), %eax
+        /* Get the host CPU in the state expected by generated code. */
 
        /* set host FPU control word to the default mode expected 
            by VEX-generated code.  See comments in libvex.h for
@@ -110,140 +97,32 @@ VG_(run_innerloop):
 L1:
        /* set dir flag to known value */
        cld
-       
-       /* fall into main loop (the right one) */
-       cmpl    $0, 32(%esp) /* do_profiling */
-       je      VG_(run_innerloop__dispatch_unassisted_unprofiled)
-       jmp     VG_(run_innerloop__dispatch_unassisted_profiled)
-       /*NOTREACHED*/
-
-/*----------------------------------------------------*/
-/*--- NO-PROFILING (standard) dispatcher           ---*/
-/*----------------------------------------------------*/
-
-.globl VG_(run_innerloop__dispatch_unassisted_unprofiled)
-VG_(run_innerloop__dispatch_unassisted_unprofiled):
-       /* AT ENTRY: %eax is next guest addr, %ebp is the
-           unmodified guest state ptr */
-
-       /* save the jump address in the guest state */
-       movl    %eax, OFFSET_x86_EIP(%ebp)
-
-       /* Are we out of timeslice?  If yes, defer to scheduler. */
-       subl    $1, VG_(dispatch_ctr)
-       jz      counter_is_zero
 
-       /* try a fast lookup in the translation cache */
-       movl    %eax, %ebx
-       andl    $VG_TT_FAST_MASK, %ebx
-       movl    0+VG_(tt_fast)(,%ebx,8), %esi   /* .guest */
-       movl    4+VG_(tt_fast)(,%ebx,8), %edi   /* .host */
-       cmpl    %eax, %esi
-       jnz     fast_lookup_failed
-
-       /* Found a match.  Jump to .host. */
-       jmp     *%edi
-       ud2     /* persuade insn decoders not to speculate past here */
-       /* generated code should run, then jump back to
-          VG_(run_innerloop__dispatch_{un,}assisted_unprofiled). */
-       /*NOTREACHED*/
-
-.globl VG_(run_innerloop__dispatch_assisted_unprofiled)
-VG_(run_innerloop__dispatch_assisted_unprofiled):
-       /* AT ENTRY: %eax is next guest addr, %ebp is the
-           modified guest state ptr */
-        jmp     gsp_changed
-        ud2
-        /*NOTREACHED*/
-
-/*----------------------------------------------------*/
-/*--- PROFILING dispatcher (can be much slower)    ---*/
-/*----------------------------------------------------*/
-
-.globl VG_(run_innerloop__dispatch_unassisted_profiled)
-VG_(run_innerloop__dispatch_unassisted_profiled):
-       /* AT ENTRY: %eax is next guest addr, %ebp is the
-           unmodified guest state ptr */
-
-       /* save the jump address in the guest state */
-       movl    %eax, OFFSET_x86_EIP(%ebp)
-
-       /* Are we out of timeslice?  If yes, defer to scheduler. */
-       subl    $1, VG_(dispatch_ctr)
-       jz      counter_is_zero
-
-       /* try a fast lookup in the translation cache */
-       movl    %eax, %ebx
-       andl    $VG_TT_FAST_MASK, %ebx
-       movl    0+VG_(tt_fast)(,%ebx,8), %esi   /* .guest */
-       movl    4+VG_(tt_fast)(,%ebx,8), %edi   /* .host */
-       cmpl    %eax, %esi
-       jnz     fast_lookup_failed
-       /* increment bb profile counter */
-       /* note: innocuous as this sounds, it causes a huge amount more
-           stress on D1 and significantly slows everything down. */
-       movl    VG_(tt_fastN)(,%ebx,4), %edx
-       /* Use "addl $1", not "incl", to avoid partial-flags stall on P4 */
-       addl    $1, (%edx)
-
-       /* Found a match.  Jump to .host. */
-       jmp     *%edi
-       ud2     /* persuade insn decoders not to speculate past here */
-       /* generated code should run, then jump back to
-          VG_(run_innerloop__dispatch_{un,}assisted_profiled). */
+       /* Set up the guest state pointer */
+       movl    28+8(%esp), %ebp
+
+        /* and jump into the code cache.  Chained translations in
+           the code cache run, until for whatever reason, they can't
+           continue.  When that happens, the translation in question
+           will jump (or call) to one of the continuation points
+           VG_(cp_...) below. */
+        jmpl    *28+12(%esp)
        /*NOTREACHED*/
 
-.globl VG_(run_innerloop__dispatch_assisted_profiled)
-VG_(run_innerloop__dispatch_assisted_profiled):
-       /* AT ENTRY: %eax is next guest addr, %ebp is the
-           modified guest state ptr */
-        jmp     gsp_changed
-        ud2
-        /*NOTREACHED*/
-
 /*----------------------------------------------------*/
-/*--- exit points                                  ---*/
+/*--- Postamble and exit.                          ---*/
 /*----------------------------------------------------*/
 
-gsp_changed:
-       /* Someone messed with the gsp.  Have to
-           defer to scheduler to resolve this.  dispatch ctr
-          is not yet decremented, so no need to increment. */
-       /* %EIP is NOT up to date here.  First, need to write
-          %eax back to %EIP, but without trashing %ebp since
-          that holds the value we want to return to the scheduler.
-          Hence use %esi transiently for the guest state pointer. */
-       movl    28(%esp), %esi
-       movl    %eax, OFFSET_x86_EIP(%esi)
-       movl    %ebp, %eax
-       jmp     run_innerloop_exit
-       /*NOTREACHED*/
+postamble:
+        /* At this point, %eax and %edx contain two
+           words to be returned to the caller.  %eax
+           holds a TRC value, and %edx optionally may
+           hold another word (for CHAIN_ME exits, the
+           address of the place to patch.) */
 
-counter_is_zero:
-       /* %EIP is up to date here */
-       /* back out decrement of the dispatch counter */
-       addl    $1, VG_(dispatch_ctr)
-       movl    $VG_TRC_INNER_COUNTERZERO, %eax
-       jmp     run_innerloop_exit
-       /*NOTREACHED*/
-
-fast_lookup_failed:
-       /* %EIP is up to date here */
-       /* back out decrement of the dispatch counter */
-       addl    $1, VG_(dispatch_ctr)
-       movl    $VG_TRC_INNER_FASTMISS, %eax
-       jmp     run_innerloop_exit
-       /*NOTREACHED*/
-
-
-
-/* All exits from the dispatcher go through here.  %eax holds
-   the return value. 
-*/
-run_innerloop_exit: 
-       /* We're leaving.  Check that nobody messed with
-           %mxcsr or %fpucw.  We can't mess with %eax here as it
-          holds the tentative return value, but any other is OK. */
+       /* We're leaving.  Check that nobody messed with %mxcsr
+           or %fpucw.  We can't mess with %eax or %edx here as they
+          holds the tentative return value, but any others are OK. */
 #if !defined(ENABLE_INNER)
         /* This check fails for self-hosting, so skip in that case */
        pushl   $0
@@ -252,7 +131,7 @@ run_innerloop_exit:
        popl    %esi /* get rid of the word without trashing %eflags */
        jnz     invariant_violation
 #endif
-       cmpl    $0, VG_(machine_x86_have_mxcsr)
+#      cmpl    $0, VG_(machine_x86_have_mxcsr)
        jz      L2
        pushl   $0
        stmxcsr (%esp)
@@ -261,69 +140,107 @@ run_innerloop_exit:
        popl    %esi
        jnz     invariant_violation
 L2:    /* otherwise we're OK */
-       jmp     run_innerloop_exit_REALLY
-
+       jmp     remove_frame
 invariant_violation:
        movl    $VG_TRC_INVARIANT_FAILED, %eax
-       jmp     run_innerloop_exit_REALLY
-
-run_innerloop_exit_REALLY:
+        movl    $0, %edx
+
+remove_frame:
+        /* Stash return values */
+        movl    28+4(%esp), %edi        /* two_words */
+        movl    %eax, 0(%edi)
+        movl    %edx, 4(%edi)
+        /* Restore int regs and return. */
        popl    %ebp
        popl    %edi
        popl    %esi
        popl    %edx
        popl    %ecx
        popl    %ebx
+       popl    %eax
        ret     
+        
+/*----------------------------------------------------*/
+/*--- Continuation points                          ---*/
+/*----------------------------------------------------*/
 
+/* ------ Chain me to slow entry point ------ */
+.globl VG_(disp_cp_chain_me_to_slowEP)
+VG_(disp_cp_chain_me_to_slowEP):
+        /* We got called.  The return address indicates
+           where the patching needs to happen.  Collect
+           the return address and, exit back to C land,
+           handing the caller the pair (Chain_me_S, RA) */
+        movl    $VG_TRC_CHAIN_ME_TO_SLOW_EP, %eax
+        popl    %edx
+        /* 5 = movl $VG_(disp_chain_me_to_slowEP), %edx;
+           2 = call *%edx */
+        subl    $5+2, %edx
+        jmp     postamble
+
+/* ------ Chain me to fast entry point ------ */
+.globl VG_(disp_cp_chain_me_to_fastEP)
+VG_(disp_cp_chain_me_to_fastEP):
+        /* We got called.  The return address indicates
+           where the patching needs to happen.  Collect
+           the return address and, exit back to C land,
+           handing the caller the pair (Chain_me_F, RA) */
+        movl    $VG_TRC_CHAIN_ME_TO_FAST_EP, %eax
+        popl    %edx
+        /* 5 = movl $VG_(disp_chain_me_to_fastEP), %edx;
+           2 = call *%edx */
+        subl    $5+2, %edx
+        jmp     postamble
+
+/* ------ Indirect but boring jump ------ */
+.globl VG_(disp_cp_xindir)
+VG_(disp_cp_xindir):
+       /* Where are we going? */
+       movl    OFFSET_x86_EIP(%ebp), %eax
 
-/*------------------------------------------------------------*/
-/*---                                                      ---*/
-/*--- A special dispatcher, for running no-redir           ---*/
-/*--- translations.  Just runs the given translation once. ---*/
-/*---                                                      ---*/
-/*------------------------------------------------------------*/
+        /* RM ME -- stats only */
+        addl    $1, _vgPlain_stats__n_xindirs
+        adcl    $0, _vgPlain_stats__n_xindirs+4
+        
+        /* try a fast lookup in the translation cache */
+        movl    %eax, %ebx                      /* next guest addr */
+        andl    $VG_TT_FAST_MASK, %ebx          /* entry# */
+        movl    0+VG_(tt_fast)(,%ebx,8), %esi   /* .guest */
+        movl    4+VG_(tt_fast)(,%ebx,8), %edi   /* .host */
+        cmpl    %eax, %esi
+        jnz     fast_lookup_failed
+
+        /* Found a match.  Jump to .host. */
+       jmp     *%edi
+       ud2     /* persuade insn decoders not to speculate past here */
 
-/* signature:
-void VG_(run_a_noredir_translation) ( UWord* argblock );
-*/
+fast_lookup_failed:
+        /* RM ME -- stats only */
+        addl    $1, _vgPlain_stats__n_xindir_misses
+        adcl    $0, _vgPlain_stats__n_xindir_misses+4
+
+       movl    $VG_TRC_INNER_FASTMISS, %eax
+        movl    $0, %edx
+       jmp     postamble
+
+/* ------ Assisted jump ------ */
+.globl VG_(disp_cp_xassisted)
+VG_(disp_cp_xassisted):
+        /* %ebp contains the TRC */
+        movl    %ebp, %eax
+        movl    $0, %edx
+        jmp     postamble
+
+/* ------ Event check failed ------ */
+.globl VG_(disp_cp_evcheck_fail)
+VG_(disp_cp_evcheck_fail):
+               movl    $VG_TRC_INNER_COUNTERZERO, %eax
+        movl    $0, %edx
+       jmp     postamble
 
-/* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
-   and 2 to carry results:
-      0: input:  ptr to translation
-      1: input:  ptr to guest state
-      2: output: next guest PC
-      3: output: guest state pointer afterwards (== thread return code)
-*/
-.globl VG_(run_a_noredir_translation)
-VG_(run_a_noredir_translation):
-       /* Save callee-saves regs */
-       pushl %esi
-       pushl %edi
-       pushl %ebp
-       pushl %ebx
-
-       movl 20(%esp), %edi     /* %edi = argblock */
-       movl 4(%edi), %ebp      /* argblock[1] */
-       jmp *0(%edi)            /* argblock[0] */
-       /*NOTREACHED*/
-       ud2
-       /* If the translation has been correctly constructed, we
-       should resume at the the following label. */
-.globl VG_(run_a_noredir_translation__return_point)
-VG_(run_a_noredir_translation__return_point):
-       movl 20(%esp), %edi
-       movl %eax, 8(%edi)      /* argblock[2] */
-       movl %ebp, 12(%edi)     /* argblock[3] */
-
-       popl %ebx
-       popl %ebp
-       popl %edi
-       popl %esi
-       ret
 
 #endif // defined(VGP_x86_darwin)
-                       
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/