blob: bd1c5b959f12c11ade1fde7d0abddb9fb292bd88 [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
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
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_constants.h"
33
34
35/*------------------------------------------------------------*/
36/*--- The normal-case dispatch machinery. ---*/
37/*------------------------------------------------------------*/
38
39/* To transfer to an (original) code address, load it into %eax and
40 jump to vg_dispatch. This fragment of code tries to find the
41 address of the corresponding translation by searching the translation
42 table. If it fails, a new translation is made, added to the
43 translation table, and then jumped to. Almost all the hard
44 work is done by C routines; this code simply handles the
45 common case fast -- when the translation address is found in
46 the translation cache.
47
48 At entry, %eax is the only live (real-machine) register; the
49 entire simulated state is tidily saved in vg_m_state.
50*/
51
52
53/* The C world needs a way to get started simulating. So we provide
54 a function void vg_run_innerloop ( void ), which starts running
55 from vg_m_eip, and exits when the counter reaches zero. This loop
56 can also exit if vg_oursignalhandler() catches a non-resumable
57 signal, for example SIGSEGV. It then longjmp()s back past here.
58*/
59
60.globl VG_(run_innerloop)
61VG_(run_innerloop):
62 #OYNK(1000)
sewardj2e93c502002-04-12 11:12:52 +000063
sewardjde4a1d02002-03-22 01:27:54 +000064 # ----- entry point to VG_(run_innerloop) -----
sewardj2e93c502002-04-12 11:12:52 +000065 pushl %ebx
66 pushl %ecx
67 pushl %edx
68 pushl %esi
69 pushl %edi
70 pushl %ebp
71
sewardjde4a1d02002-03-22 01:27:54 +000072 # Set up the baseBlock pointer
73 movl $VG_(baseBlock), %ebp
74
75 # fetch m_eip into %eax
76 movl VGOFF_(m_eip), %esi
77 movl (%ebp, %esi, 4), %eax
78
sewardj2e93c502002-04-12 11:12:52 +000079 # Start off dispatching paranoically, since we no longer have
80 # any indication whether or not this might be a special call/ret
81 # transfer.
sewardj54cacf02002-04-12 23:24:59 +000082 jmp dispatch_stkadj
sewardjde4a1d02002-03-22 01:27:54 +000083
sewardj2e93c502002-04-12 11:12:52 +000084
85dispatch_main:
86 # Jump here to do a new dispatch.
87 # %eax holds destination (original) address.
sewardjde4a1d02002-03-22 01:27:54 +000088 # %ebp indicates further details of the control transfer
sewardj54cacf02002-04-12 23:24:59 +000089 # requested to the address in %eax.
sewardjde4a1d02002-03-22 01:27:54 +000090 #
sewardj54cacf02002-04-12 23:24:59 +000091 # If ebp == & VG_(baseBlock), just jump next to %eax.
sewardjde4a1d02002-03-22 01:27:54 +000092 #
sewardj2e93c502002-04-12 11:12:52 +000093 # If ebp == VG_EBP_JMP_SYSCALL, do a system call before
94 # continuing at eax.
95 #
96 # If ebp == VG_EBP_JMP_CLIENTREQ, do a client request before
97 # continuing at eax.
98 #
sewardjde4a1d02002-03-22 01:27:54 +000099 # If %ebp has any other value, we panic.
sewardj2e93c502002-04-12 11:12:52 +0000100
sewardjde4a1d02002-03-22 01:27:54 +0000101 cmpl $VG_(baseBlock), %ebp
sewardj2e93c502002-04-12 11:12:52 +0000102 jnz dispatch_exceptional
sewardjde4a1d02002-03-22 01:27:54 +0000103
sewardj2e93c502002-04-12 11:12:52 +0000104dispatch_boring:
sewardjde4a1d02002-03-22 01:27:54 +0000105 # save the jump address at VG_(baseBlock)[VGOFF_(m_eip)],
sewardjde4a1d02002-03-22 01:27:54 +0000106 movl VGOFF_(m_eip), %esi
107 movl %eax, (%ebp, %esi, 4)
108
sewardj2e93c502002-04-12 11:12:52 +0000109 # do a timeslice check.
110 # are we out of timeslice? If yes, defer to scheduler.
sewardjde4a1d02002-03-22 01:27:54 +0000111 #OYNK(1001)
112 decl VG_(dispatch_ctr)
113 jz counter_is_zero
114
115 #OYNK(1002)
116 # try a fast lookup in the translation cache
117 movl %eax, %ebx
118 andl $VG_TT_FAST_MASK, %ebx
119 # ebx = tt_fast index
120 movl VG_(tt_fast)(,%ebx,4), %ebx
121 # ebx points at a tt entry
122 # now compare target with the tte.orig_addr field (+0)
123 cmpl %eax, (%ebx)
sewardj2e93c502002-04-12 11:12:52 +0000124 jnz fast_lookup_failed
125
sewardjde4a1d02002-03-22 01:27:54 +0000126 # Found a match. Set the tte.mru_epoch field (+8)
127 # and call the tte.trans_addr field (+4)
128 movl VG_(current_epoch), %ecx
129 movl %ecx, 8(%ebx)
130 call *4(%ebx)
sewardj2e93c502002-04-12 11:12:52 +0000131 jmp dispatch_main
sewardjde4a1d02002-03-22 01:27:54 +0000132
sewardj2e93c502002-04-12 11:12:52 +0000133fast_lookup_failed:
134 # %EIP is up to date here since dispatch_boring dominates
135 movl $VG_TRC_INNER_FASTMISS, %eax
136 jmp run_innerloop_exit
sewardjde4a1d02002-03-22 01:27:54 +0000137
sewardjde4a1d02002-03-22 01:27:54 +0000138counter_is_zero:
sewardj2e93c502002-04-12 11:12:52 +0000139 # %EIP is up to date here since dispatch_boring dominates
140 movl $VG_TRC_INNER_COUNTERZERO, %eax
141 jmp run_innerloop_exit
sewardjde4a1d02002-03-22 01:27:54 +0000142
sewardj2e93c502002-04-12 11:12:52 +0000143run_innerloop_exit:
sewardjde4a1d02002-03-22 01:27:54 +0000144 popl %ebp
145 popl %edi
146 popl %esi
147 popl %edx
148 popl %ecx
149 popl %ebx
sewardj2e93c502002-04-12 11:12:52 +0000150 ret
151
152
153
154/* Other ways of getting out of the inner loop. Placed out-of-line to
155 make it look cleaner.
156*/
157dispatch_exceptional:
158 # this is jumped to only, not fallen-through from above
sewardj54cacf02002-04-12 23:24:59 +0000159 cmpl $VG_TRC_EBP_JMP_STKADJ, %ebp
160 jz dispatch_stkadj
sewardj2e93c502002-04-12 11:12:52 +0000161 cmpl $VG_TRC_EBP_JMP_SYSCALL, %ebp
162 jz dispatch_syscall
163 cmpl $VG_TRC_EBP_JMP_CLIENTREQ, %ebp
164 jz dispatch_clientreq
165
166 # ebp has an invalid value ... crap out.
167 pushl $panic_msg_ebp
168 call VG_(panic)
169 # (never returns)
170
171dispatch_syscall:
172 # save %eax in %EIP and defer to sched
173 movl $VG_(baseBlock), %ebp
174 movl VGOFF_(m_eip), %esi
175 movl %eax, (%ebp, %esi, 4)
176 movl $VG_TRC_EBP_JMP_SYSCALL, %eax
177 jmp run_innerloop_exit
sewardjde4a1d02002-03-22 01:27:54 +0000178
sewardj2e93c502002-04-12 11:12:52 +0000179dispatch_clientreq:
180 # save %eax in %EIP and defer to sched
181 movl $VG_(baseBlock), %ebp
182 movl VGOFF_(m_eip), %esi
183 movl %eax, (%ebp, %esi, 4)
184 movl $VG_TRC_EBP_JMP_CLIENTREQ, %eax
185 jmp run_innerloop_exit
186
sewardj54cacf02002-04-12 23:24:59 +0000187dispatch_stkadj:
sewardj2e93c502002-04-12 11:12:52 +0000188 # save %eax in %EIP
189 movl $VG_(baseBlock), %ebp
190 movl VGOFF_(m_eip), %esi
191 movl %eax, (%ebp, %esi, 4)
192
193 # see if we need to mess with stack blocks
194 pushl %eax
195 call VG_(delete_client_stack_blocks_following_ESP_change)
196 popl %eax
197 movl $VG_(baseBlock), %ebp
sewardj54cacf02002-04-12 23:24:59 +0000198
sewardj2e93c502002-04-12 11:12:52 +0000199 # ok, its not interesting. Handle the normal way.
200 jmp dispatch_boring
201
sewardj2e93c502002-04-12 11:12:52 +0000202
203.data
204panic_msg_ebp:
205.ascii "vg_dispatch: %ebp has invalid value!"
206.byte 0
207.text
208
sewardjde4a1d02002-03-22 01:27:54 +0000209
210##--------------------------------------------------------------------##
211##--- end vg_dispatch.S ---##
212##--------------------------------------------------------------------##