blob: a1b556913004467b2ddf60b9d9006ab3aa205b66 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2##--------------------------------------------------------------------##
3##--- The core dispatch loop, for jumping to a code address. ---##
4##--- vg_dispatch.S ---##
5##--------------------------------------------------------------------##
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
13 Julian_Seward@muraroa.demon.co.uk
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file LICENSE.
31*/
32
33#include "vg_constants.h"
34
35
36/*------------------------------------------------------------*/
37/*--- The normal-case dispatch machinery. ---*/
38/*------------------------------------------------------------*/
39
40/* To transfer to an (original) code address, load it into %eax and
41 jump to vg_dispatch. This fragment of code tries to find the
42 address of the corresponding translation by searching the translation
43 table. If it fails, a new translation is made, added to the
44 translation table, and then jumped to. Almost all the hard
45 work is done by C routines; this code simply handles the
46 common case fast -- when the translation address is found in
47 the translation cache.
48
49 At entry, %eax is the only live (real-machine) register; the
50 entire simulated state is tidily saved in vg_m_state.
51*/
52
53
54/* The C world needs a way to get started simulating. So we provide
55 a function void vg_run_innerloop ( void ), which starts running
56 from vg_m_eip, and exits when the counter reaches zero. This loop
57 can also exit if vg_oursignalhandler() catches a non-resumable
58 signal, for example SIGSEGV. It then longjmp()s back past here.
59*/
60
61.globl VG_(run_innerloop)
62VG_(run_innerloop):
63 #OYNK(1000)
sewardj2e93c502002-04-12 11:12:52 +000064
sewardjde4a1d02002-03-22 01:27:54 +000065 # ----- entry point to VG_(run_innerloop) -----
sewardj2e93c502002-04-12 11:12:52 +000066 pushl %ebx
67 pushl %ecx
68 pushl %edx
69 pushl %esi
70 pushl %edi
71 pushl %ebp
72
sewardjde4a1d02002-03-22 01:27:54 +000073 # Set up the baseBlock pointer
74 movl $VG_(baseBlock), %ebp
75
76 # fetch m_eip into %eax
77 movl VGOFF_(m_eip), %esi
78 movl (%ebp, %esi, 4), %eax
79
sewardj2e93c502002-04-12 11:12:52 +000080 # Start off dispatching paranoically, since we no longer have
81 # any indication whether or not this might be a special call/ret
82 # transfer.
sewardj54cacf02002-04-12 23:24:59 +000083 jmp dispatch_stkadj
sewardjde4a1d02002-03-22 01:27:54 +000084
sewardj2e93c502002-04-12 11:12:52 +000085
86dispatch_main:
87 # Jump here to do a new dispatch.
88 # %eax holds destination (original) address.
sewardjde4a1d02002-03-22 01:27:54 +000089 # %ebp indicates further details of the control transfer
sewardj54cacf02002-04-12 23:24:59 +000090 # requested to the address in %eax.
sewardjde4a1d02002-03-22 01:27:54 +000091 #
sewardj54cacf02002-04-12 23:24:59 +000092 # If ebp == & VG_(baseBlock), just jump next to %eax.
sewardjde4a1d02002-03-22 01:27:54 +000093 #
sewardj2e93c502002-04-12 11:12:52 +000094 # If ebp == VG_EBP_JMP_SYSCALL, do a system call before
95 # continuing at eax.
96 #
97 # If ebp == VG_EBP_JMP_CLIENTREQ, do a client request before
98 # continuing at eax.
99 #
sewardjde4a1d02002-03-22 01:27:54 +0000100 # If %ebp has any other value, we panic.
sewardj2e93c502002-04-12 11:12:52 +0000101
sewardjde4a1d02002-03-22 01:27:54 +0000102 cmpl $VG_(baseBlock), %ebp
sewardj2e93c502002-04-12 11:12:52 +0000103 jnz dispatch_exceptional
sewardjde4a1d02002-03-22 01:27:54 +0000104
sewardj2e93c502002-04-12 11:12:52 +0000105dispatch_boring:
sewardjde4a1d02002-03-22 01:27:54 +0000106 # save the jump address at VG_(baseBlock)[VGOFF_(m_eip)],
sewardjde4a1d02002-03-22 01:27:54 +0000107 movl VGOFF_(m_eip), %esi
108 movl %eax, (%ebp, %esi, 4)
109
sewardj2e93c502002-04-12 11:12:52 +0000110 # do a timeslice check.
111 # are we out of timeslice? If yes, defer to scheduler.
sewardjde4a1d02002-03-22 01:27:54 +0000112 #OYNK(1001)
113 decl VG_(dispatch_ctr)
114 jz counter_is_zero
115
116 #OYNK(1002)
117 # try a fast lookup in the translation cache
118 movl %eax, %ebx
119 andl $VG_TT_FAST_MASK, %ebx
120 # ebx = tt_fast index
121 movl VG_(tt_fast)(,%ebx,4), %ebx
122 # ebx points at a tt entry
123 # now compare target with the tte.orig_addr field (+0)
124 cmpl %eax, (%ebx)
sewardj2e93c502002-04-12 11:12:52 +0000125 jnz fast_lookup_failed
126
sewardjde4a1d02002-03-22 01:27:54 +0000127 # Found a match. Set the tte.mru_epoch field (+8)
128 # and call the tte.trans_addr field (+4)
129 movl VG_(current_epoch), %ecx
130 movl %ecx, 8(%ebx)
131 call *4(%ebx)
sewardj2e93c502002-04-12 11:12:52 +0000132 jmp dispatch_main
sewardjde4a1d02002-03-22 01:27:54 +0000133
sewardj2e93c502002-04-12 11:12:52 +0000134fast_lookup_failed:
135 # %EIP is up to date here since dispatch_boring dominates
136 movl $VG_TRC_INNER_FASTMISS, %eax
137 jmp run_innerloop_exit
sewardjde4a1d02002-03-22 01:27:54 +0000138
sewardjde4a1d02002-03-22 01:27:54 +0000139counter_is_zero:
sewardj2e93c502002-04-12 11:12:52 +0000140 # %EIP is up to date here since dispatch_boring dominates
141 movl $VG_TRC_INNER_COUNTERZERO, %eax
142 jmp run_innerloop_exit
sewardjde4a1d02002-03-22 01:27:54 +0000143
sewardj2e93c502002-04-12 11:12:52 +0000144run_innerloop_exit:
sewardjde4a1d02002-03-22 01:27:54 +0000145 popl %ebp
146 popl %edi
147 popl %esi
148 popl %edx
149 popl %ecx
150 popl %ebx
sewardj2e93c502002-04-12 11:12:52 +0000151 ret
152
153
154
155/* Other ways of getting out of the inner loop. Placed out-of-line to
156 make it look cleaner.
157*/
158dispatch_exceptional:
159 # this is jumped to only, not fallen-through from above
sewardj54cacf02002-04-12 23:24:59 +0000160 cmpl $VG_TRC_EBP_JMP_STKADJ, %ebp
161 jz dispatch_stkadj
sewardj2e93c502002-04-12 11:12:52 +0000162 cmpl $VG_TRC_EBP_JMP_SYSCALL, %ebp
163 jz dispatch_syscall
164 cmpl $VG_TRC_EBP_JMP_CLIENTREQ, %ebp
165 jz dispatch_clientreq
166
167 # ebp has an invalid value ... crap out.
168 pushl $panic_msg_ebp
169 call VG_(panic)
170 # (never returns)
171
172dispatch_syscall:
173 # save %eax in %EIP and defer to sched
174 movl $VG_(baseBlock), %ebp
175 movl VGOFF_(m_eip), %esi
176 movl %eax, (%ebp, %esi, 4)
177 movl $VG_TRC_EBP_JMP_SYSCALL, %eax
178 jmp run_innerloop_exit
sewardjde4a1d02002-03-22 01:27:54 +0000179
sewardj2e93c502002-04-12 11:12:52 +0000180dispatch_clientreq:
181 # save %eax in %EIP and defer to sched
182 movl $VG_(baseBlock), %ebp
183 movl VGOFF_(m_eip), %esi
184 movl %eax, (%ebp, %esi, 4)
185 movl $VG_TRC_EBP_JMP_CLIENTREQ, %eax
186 jmp run_innerloop_exit
187
sewardj54cacf02002-04-12 23:24:59 +0000188dispatch_stkadj:
sewardj2e93c502002-04-12 11:12:52 +0000189 # save %eax in %EIP
190 movl $VG_(baseBlock), %ebp
191 movl VGOFF_(m_eip), %esi
192 movl %eax, (%ebp, %esi, 4)
193
194 # see if we need to mess with stack blocks
195 pushl %eax
196 call VG_(delete_client_stack_blocks_following_ESP_change)
197 popl %eax
198 movl $VG_(baseBlock), %ebp
sewardj54cacf02002-04-12 23:24:59 +0000199
sewardj2e93c502002-04-12 11:12:52 +0000200 # ok, its not interesting. Handle the normal way.
201 jmp dispatch_boring
202
sewardj2e93c502002-04-12 11:12:52 +0000203
204.data
205panic_msg_ebp:
206.ascii "vg_dispatch: %ebp has invalid value!"
207.byte 0
208.text
209
sewardjde4a1d02002-03-22 01:27:54 +0000210
211##--------------------------------------------------------------------##
212##--- end vg_dispatch.S ---##
213##--------------------------------------------------------------------##