blob: 68ef2297117ebdec497572568a0caa9d6c1a1196 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
njnc9539842002-10-02 13:26:35 +00002##--------------------------------------------------------------------##
3##--- The core dispatch loop, for jumping to a code address. ---##
njnbb120952004-11-23 18:19:29 +00004##--- x86/dispatch.S ---##
njnc9539842002-10-02 13:26:35 +00005##--------------------------------------------------------------------##
sewardjde4a1d02002-03-22 01:27:54 +00006
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn53612422005-03-12 16:22:54 +000011 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
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
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
nethercote5a2664c2004-09-02 15:37:39 +000032#include "core_asm.h"
njna733b5f2005-05-12 13:15:38 +000033#include "pub_core_dispatch_asm.h"
sewardj0312f512005-03-30 19:04:29 +000034#include "libvex_guest_offsets.h" /* for OFFSET_x86_EIP */
sewardjde4a1d02002-03-22 01:27:54 +000035
36
37/*------------------------------------------------------------*/
njnd6f157d2004-11-30 17:27:21 +000038/*--- The dispatch loop. ---*/
sewardjde4a1d02002-03-22 01:27:54 +000039/*------------------------------------------------------------*/
sewardj0312f512005-03-30 19:04:29 +000040
41/* signature: UWord VG_(run_innerloop) ( void* guest_state ) */
sewardj2a99cf62004-11-24 10:44:19 +000042
sewardjde4a1d02002-03-22 01:27:54 +000043.globl VG_(run_innerloop)
44VG_(run_innerloop):
sewardj2a99cf62004-11-24 10:44:19 +000045 /* 4(%esp) holds guest_state */
46
njn25e49d8e72002-09-23 09:36:25 +000047 /* ----- entry point to VG_(run_innerloop) ----- */
sewardj2e93c502002-04-12 11:12:52 +000048 pushl %ebx
49 pushl %ecx
50 pushl %edx
51 pushl %esi
52 pushl %edi
53 pushl %ebp
fitzhardinge98abfc72003-12-16 02:05:15 +000054
sewardj2a99cf62004-11-24 10:44:19 +000055 /* 28(%esp) holds guest_state */
fitzhardinge98abfc72003-12-16 02:05:15 +000056
njnbd2e75c2004-11-24 16:43:43 +000057 /* Set up the guest state pointer */
sewardj2a99cf62004-11-24 10:44:19 +000058 movl 28(%esp), %ebp
59
njnd6f157d2004-11-30 17:27:21 +000060 /* fetch %EIP into %eax */
sewardj0312f512005-03-30 19:04:29 +000061 movl OFFSET_x86_EIP(%ebp), %eax
sewardjff992722004-12-04 01:45:56 +000062
sewardjaa561fa2004-12-06 14:23:28 +000063 /* set host FPU control word to the default mode expected
sewardj5390e662005-01-10 16:51:14 +000064 by VEX-generated code. See comments in libvex.h for
65 more info. */
sewardjaa561fa2004-12-06 14:23:28 +000066 finit
sewardj5390e662005-01-10 16:51:14 +000067 pushl $0x027F
sewardjaa561fa2004-12-06 14:23:28 +000068 fldcw (%esp)
sewardjff992722004-12-04 01:45:56 +000069 addl $4, %esp
sewardjde4a1d02002-03-22 01:27:54 +000070
sewardjaa561fa2004-12-06 14:23:28 +000071 /* set host SSE control word to the default mode expected
72 by VEX-generated code. */
73 pushl $0x1F80
74 ldmxcsr (%esp)
75 addl $4, %esp
76
77 /* set dir flag to known value */
78 cld
79
sewardj8b635a42004-11-22 19:01:47 +000080 /* fall into main loop */
81
njnd6f157d2004-11-30 17:27:21 +000082 /* Here, %eax is the only live (real) register. The entire
83 simulated state is saved in the ThreadState. */
84
sewardj8b635a42004-11-22 19:01:47 +000085dispatch_boring:
sewardj2a99cf62004-11-24 10:44:19 +000086 /* save the jump address in the guest state */
sewardj0312f512005-03-30 19:04:29 +000087 movl %eax, OFFSET_x86_EIP(%ebp)
sewardj8b635a42004-11-22 19:01:47 +000088
89 /* Are we out of timeslice? If yes, defer to scheduler. */
90 subl $1, VG_(dispatch_ctr)
sewardj8b635a42004-11-22 19:01:47 +000091 jz counter_is_zero
sewardj45f02c42005-02-05 18:27:14 +000092
sewardj8b635a42004-11-22 19:01:47 +000093 /* try a fast lookup in the translation cache */
sewardjfa8ec112005-01-19 11:55:34 +000094 movl %eax, %ebx
95 andl $VG_TT_FAST_MASK, %ebx
96 movl VG_(tt_fast)(,%ebx,4), %ecx
97 cmpl %eax, (%ecx)
98 jnz fast_lookup_failed
sewardj45f02c42005-02-05 18:27:14 +000099 /* increment bb profile counter */
sewardjfa8ec112005-01-19 11:55:34 +0000100 movl VG_(tt_fastN)(,%ebx,4), %edx
101 incl (%edx)
sewardj8b635a42004-11-22 19:01:47 +0000102
sewardjfa8ec112005-01-19 11:55:34 +0000103 /* Found a match. Call tce[1], which is 8 bytes along, since
104 each tce element is a 64-bit int. */
sewardjfa8ec112005-01-19 11:55:34 +0000105 addl $8, %ecx
106 call *%ecx
sewardj8b635a42004-11-22 19:01:47 +0000107
108 /*
njn25e49d8e72002-09-23 09:36:25 +0000109 %eax holds destination (original) address.
110 %ebp indicates further details of the control transfer
111 requested to the address in %eax.
sewardj2e93c502002-04-12 11:12:52 +0000112
sewardj2a99cf62004-11-24 10:44:19 +0000113 If ebp is unchanged (== * 28(%esp)), just jump next to %eax.
sewardj1ff79572004-11-30 11:18:57 +0000114
115 Otherwise fall out, back to the scheduler, and let it
116 figure out what to do next.
njn25e49d8e72002-09-23 09:36:25 +0000117 */
njn25e49d8e72002-09-23 09:36:25 +0000118
sewardj2a99cf62004-11-24 10:44:19 +0000119 cmpl 28(%esp), %ebp
njn25e49d8e72002-09-23 09:36:25 +0000120 jz dispatch_boring
121
122 jmp dispatch_exceptional
123
sewardjde4a1d02002-03-22 01:27:54 +0000124
sewardjde4a1d02002-03-22 01:27:54 +0000125
sewardj5390e662005-01-10 16:51:14 +0000126/* All exits from the dispatcher go through here. %eax holds
127 the return value.
128*/
129run_innerloop_exit:
130 /* We're leaving. Check that nobody messed with
131 %mxcsr or %fpucw. We can't mess with %eax here as it
132 holds the tentative return value, but any other is OK. */
133 pushl $0
134 fstcw (%esp)
135 cmpl $0x027F, (%esp)
136 popl %esi /* get rid of the word without trashing %eflags */
137 jnz invariant_violation
138 pushl $0
139 stmxcsr (%esp)
140 andl $0xFFFFFFC0, (%esp) /* mask out status flags */
141 cmpl $0x1F80, (%esp)
142 popl %esi
143 jnz invariant_violation
144 /* otherwise we're OK */
145 jmp run_innerloop_exit_REALLY
146
147invariant_violation:
148 movl $VG_TRC_INVARIANT_FAILED, %eax
149 jmp run_innerloop_exit_REALLY
150
151run_innerloop_exit_REALLY:
sewardj2a99cf62004-11-24 10:44:19 +0000152 popl %ebp
sewardjde4a1d02002-03-22 01:27:54 +0000153 popl %edi
154 popl %esi
155 popl %edx
156 popl %ecx
157 popl %ebx
sewardj2e93c502002-04-12 11:12:52 +0000158 ret
159
160
161
162/* Other ways of getting out of the inner loop. Placed out-of-line to
163 make it look cleaner.
164*/
165dispatch_exceptional:
njn25e49d8e72002-09-23 09:36:25 +0000166 /* this is jumped to only, not fallen-through from above */
sewardj22854b92002-11-30 14:00:47 +0000167 cmpl $VG_TRC_INNER_COUNTERZERO, %ebp
168 jz counter_is_zero
sewardj2e93c502002-04-12 11:12:52 +0000169
njn25e49d8e72002-09-23 09:36:25 +0000170 /* save %eax in %EIP and defer to sched */
sewardj2a99cf62004-11-24 10:44:19 +0000171 movl 28(%esp), %edi
sewardj0312f512005-03-30 19:04:29 +0000172 movl %eax, OFFSET_x86_EIP(%edi)
fitzhardingea02f8812003-12-18 09:06:09 +0000173 movl %ebp, %eax
sewardj2e93c502002-04-12 11:12:52 +0000174 jmp run_innerloop_exit
175
sewardj5390e662005-01-10 16:51:14 +0000176fast_lookup_failed:
177 /* %EIP is up to date here since dispatch_boring dominates */
178 addl $1, VG_(dispatch_ctr)
179 movl $VG_TRC_INNER_FASTMISS, %eax
180 jmp run_innerloop_exit
181
182counter_is_zero:
183 /* %EIP is up to date here since dispatch_boring dominates */
184 addl $1, VG_(dispatch_ctr)
185 movl $VG_TRC_INNER_COUNTERZERO, %eax
186 jmp run_innerloop_exit
187
sewardj22854b92002-11-30 14:00:47 +0000188
thughes4ad52d02004-06-27 17:37:21 +0000189/* Let the linker know we don't need an executable stack */
190.section .note.GNU-stack,"",@progbits
sewardjde4a1d02002-03-22 01:27:54 +0000191
njnc9539842002-10-02 13:26:35 +0000192##--------------------------------------------------------------------##
njnbb120952004-11-23 18:19:29 +0000193##--- end ---##
njnc9539842002-10-02 13:26:35 +0000194##--------------------------------------------------------------------##