/*------------------------------------------------------------*/
/*--- ---*/
-/*--- 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
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
/* 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
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
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)
#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
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
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
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)
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 ---*/
/*--------------------------------------------------------------------*/