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-2011 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_unassisted_unprofiled) 117 jmp VG_(run_innerloop__dispatch_unassisted_profiled) 118 /*NOTREACHED*/ 119 120/*----------------------------------------------------*/ 121/*--- NO-PROFILING (standard) dispatcher ---*/ 122/*----------------------------------------------------*/ 123 124.globl VG_(run_innerloop__dispatch_unassisted_unprofiled) 125VG_(run_innerloop__dispatch_unassisted_unprofiled): 126 /* AT ENTRY: %eax is next guest addr, %ebp is the 127 unmodified guest state ptr */ 128 129 /* save the jump address in the guest state */ 130 movl %eax, OFFSET_x86_EIP(%ebp) 131 132 /* Are we out of timeslice? If yes, defer to scheduler. */ 133 subl $1, VG_(dispatch_ctr) 134 jz counter_is_zero 135 136 /* try a fast lookup in the translation cache */ 137 movl %eax, %ebx 138 andl $VG_TT_FAST_MASK, %ebx 139 movl 0+VG_(tt_fast)(,%ebx,8), %esi /* .guest */ 140 movl 4+VG_(tt_fast)(,%ebx,8), %edi /* .host */ 141 cmpl %eax, %esi 142 jnz fast_lookup_failed 143 144 /* Found a match. Jump to .host. */ 145 jmp *%edi 146 ud2 /* persuade insn decoders not to speculate past here */ 147 /* generated code should run, then jump back to 148 VG_(run_innerloop__dispatch_{un,}assisted_unprofiled). */ 149 /*NOTREACHED*/ 150 151.globl VG_(run_innerloop__dispatch_assisted_unprofiled) 152VG_(run_innerloop__dispatch_assisted_unprofiled): 153 /* AT ENTRY: %eax is next guest addr, %ebp is the 154 modified guest state ptr */ 155 jmp gsp_changed 156 ud2 157 /*NOTREACHED*/ 158 159/*----------------------------------------------------*/ 160/*--- PROFILING dispatcher (can be much slower) ---*/ 161/*----------------------------------------------------*/ 162 163.globl VG_(run_innerloop__dispatch_unassisted_profiled) 164VG_(run_innerloop__dispatch_unassisted_profiled): 165 /* AT ENTRY: %eax is next guest addr, %ebp is the 166 unmodified guest state ptr */ 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_{un,}assisted_profiled). */ 194 /*NOTREACHED*/ 195 196.globl VG_(run_innerloop__dispatch_assisted_profiled) 197VG_(run_innerloop__dispatch_assisted_profiled): 198 /* AT ENTRY: %eax is next guest addr, %ebp is the 199 modified guest state ptr */ 200 jmp gsp_changed 201 ud2 202 /*NOTREACHED*/ 203 204/*----------------------------------------------------*/ 205/*--- exit points ---*/ 206/*----------------------------------------------------*/ 207 208gsp_changed: 209 /* Someone messed with the gsp. Have to 210 defer to scheduler to resolve this. dispatch ctr 211 is not yet decremented, so no need to increment. */ 212 /* %EIP is NOT up to date here. First, need to write 213 %eax back to %EIP, but without trashing %ebp since 214 that holds the value we want to return to the scheduler. 215 Hence use %esi transiently for the guest state pointer. */ 216 movl 28(%esp), %esi 217 movl %eax, OFFSET_x86_EIP(%esi) 218 movl %ebp, %eax 219 jmp run_innerloop_exit 220 /*NOTREACHED*/ 221 222counter_is_zero: 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_COUNTERZERO, %eax 227 jmp run_innerloop_exit 228 /*NOTREACHED*/ 229 230fast_lookup_failed: 231 /* %EIP is up to date here */ 232 /* back out decrement of the dispatch counter */ 233 addl $1, VG_(dispatch_ctr) 234 movl $VG_TRC_INNER_FASTMISS, %eax 235 jmp run_innerloop_exit 236 /*NOTREACHED*/ 237 238 239 240/* All exits from the dispatcher go through here. %eax holds 241 the return value. 242*/ 243run_innerloop_exit: 244 /* We're leaving. Check that nobody messed with 245 %mxcsr or %fpucw. We can't mess with %eax here as it 246 holds the tentative return value, but any other is OK. */ 247#if !defined(ENABLE_INNER) 248 /* This check fails for self-hosting, so skip in that case */ 249 pushl $0 250 fstcw (%esp) 251 cmpl $0x027F, (%esp) 252 popl %esi /* get rid of the word without trashing %eflags */ 253 jnz invariant_violation 254#endif 255 cmpl $0, VG_(machine_x86_have_mxcsr) 256 jz L2 257 pushl $0 258 stmxcsr (%esp) 259 andl $0xFFFFFFC0, (%esp) /* mask out status flags */ 260 cmpl $0x1F80, (%esp) 261 popl %esi 262 jnz invariant_violation 263L2: /* otherwise we're OK */ 264 jmp run_innerloop_exit_REALLY 265 266invariant_violation: 267 movl $VG_TRC_INVARIANT_FAILED, %eax 268 jmp run_innerloop_exit_REALLY 269 270run_innerloop_exit_REALLY: 271 popl %ebp 272 popl %edi 273 popl %esi 274 popl %edx 275 popl %ecx 276 popl %ebx 277 ret 278 279 280/*------------------------------------------------------------*/ 281/*--- ---*/ 282/*--- A special dispatcher, for running no-redir ---*/ 283/*--- translations. Just runs the given translation once. ---*/ 284/*--- ---*/ 285/*------------------------------------------------------------*/ 286 287/* signature: 288void VG_(run_a_noredir_translation) ( UWord* argblock ); 289*/ 290 291/* Run a no-redir translation. argblock points to 4 UWords, 2 to carry args 292 and 2 to carry results: 293 0: input: ptr to translation 294 1: input: ptr to guest state 295 2: output: next guest PC 296 3: output: guest state pointer afterwards (== thread return code) 297*/ 298.globl VG_(run_a_noredir_translation) 299VG_(run_a_noredir_translation): 300 /* Save callee-saves regs */ 301 pushl %esi 302 pushl %edi 303 pushl %ebp 304 pushl %ebx 305 306 movl 20(%esp), %edi /* %edi = argblock */ 307 movl 4(%edi), %ebp /* argblock[1] */ 308 jmp *0(%edi) /* argblock[0] */ 309 /*NOTREACHED*/ 310 ud2 311 /* If the translation has been correctly constructed, we 312 should resume at the the following label. */ 313.globl VG_(run_a_noredir_translation__return_point) 314VG_(run_a_noredir_translation__return_point): 315 movl 20(%esp), %edi 316 movl %eax, 8(%edi) /* argblock[2] */ 317 movl %ebp, 12(%edi) /* argblock[3] */ 318 319 popl %ebx 320 popl %ebp 321 popl %edi 322 popl %esi 323 ret 324 325#endif // defined(VGP_x86_darwin) 326 327/*--------------------------------------------------------------------*/ 328/*--- end ---*/ 329/*--------------------------------------------------------------------*/ 330