blob: 8c9281415306db010c80675a2bf0fc94aa8cdc47 [file] [log] [blame]
sewardj59570ff2010-01-01 11:59:33 +00001/*--------------------------------------------------------------------*/
2/*--- The core dispatch loop, for jumping to a code address. ---*/
3/*--- dispatch-arm-linux.S ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2008-2010 Evan Geller
sewardj59570ff2010-01-01 11:59:33 +000011 gaze@bea.ms
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31#if defined(VGP_arm_linux)
sewardj223125d2010-08-22 12:03:45 +000032 .fpu vfp
sewardj59570ff2010-01-01 11:59:33 +000033
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_arm_R* */
38
39
40/*------------------------------------------------------------*/
41/*--- ---*/
42/*--- The dispatch loop. VG_(run_innerloop) is used to ---*/
43/*--- run all translations except no-redir ones. ---*/
44/*--- ---*/
45/*------------------------------------------------------------*/
46
47/*----------------------------------------------------*/
48/*--- Preamble (set everything up) ---*/
49/*----------------------------------------------------*/
50
51/* signature:
52UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
53*/
54.text
55.globl VG_(run_innerloop)
56VG_(run_innerloop):
57 push {r0, r1, r4, r5, r6, r7, r8, r9, fp, lr}
58
59 /* set FPSCR to vex-required default value */
60 mov r4, #0
61 fmxr fpscr, r4
62
63 /* r0 (hence also [sp,#0]) holds guest_state */
64 /* r1 holds do_profiling */
65 mov r8, r0
sewardj223125d2010-08-22 12:03:45 +000066 ldr r0, [r8, #OFFSET_arm_R15T]
sewardj59570ff2010-01-01 11:59:33 +000067
68 /* fall into main loop (the right one) */
69 cmp r1, #0 /* do_profiling */
70 beq VG_(run_innerloop__dispatch_unprofiled)
71 b VG_(run_innerloop__dispatch_profiled)
72
73
74/*----------------------------------------------------*/
75/*--- NO-PROFILING (standard) dispatcher ---*/
76/*----------------------------------------------------*/
77
78.global VG_(run_innerloop__dispatch_unprofiled)
79VG_(run_innerloop__dispatch_unprofiled):
80
81 /* AT ENTRY: r0 is next guest addr, r8 is possibly
82 modified guest state ptr */
83
84 /* Has the guest state pointer been messed with? If yes, exit. */
85 ldr r1, [sp, #0]
86 cmp r8, r1
87 bne gsp_changed
88
89 /* save the jump address in the guest state */
sewardj223125d2010-08-22 12:03:45 +000090 str r0, [r8, #OFFSET_arm_R15T]
sewardj59570ff2010-01-01 11:59:33 +000091
92 /* Are we out of timeslice? If yes, defer to scheduler. */
93 ldr r1, =VG_(dispatch_ctr)
94 ldr r2, [r1]
95 subs r2, r2, #1
96 str r2, [r1]
97 beq counter_is_zero
98
99 /* try a fast lookup in the translation cache */
100 // r0 = next guest, r1,r2,r3 scratch
101 ldr r1, =VG_TT_FAST_MASK // r1 = VG_TT_FAST_MASK
102 and r2, r1, r0, LSR #2 // r2 = entry #
103 ldr r1, =VG_(tt_fast) // r1 = &tt_fast[0]
104 add r1, r1, r2, LSL #3 // r1 = &tt_fast[entry#]
105 ldr r3, [r1, #0] /* .guest */
106 ldr r1, [r1, #4] /* .host */
107 cmp r0, r3
108 bne fast_lookup_failed
109 // r1: live, next-host r8: live, gsp
110 // r2: entry # (but not live)
111 // r0, r3: dead
112
113 /* Found a match. Jump to .host. */
114 blx r1
115 b VG_(run_innerloop__dispatch_unprofiled)
116.ltorg
117 /*NOTREACHED*/
118
119/*----------------------------------------------------*/
120/*--- PROFILING dispatcher (can be much slower) ---*/
121/*----------------------------------------------------*/
122
123.global VG_(run_innerloop__dispatch_profiled)
124VG_(run_innerloop__dispatch_profiled):
125
126 /* AT ENTRY: r0 is next guest addr, r8 is possibly
127 modified guest state ptr */
128
129 /* Has the guest state pointer been messed with? If yes, exit. */
130 ldr r1, [sp, #0]
131 cmp r8, r1
132 bne gsp_changed
133
134 /* save the jump address in the guest state */
sewardj223125d2010-08-22 12:03:45 +0000135 str r0, [r8, #OFFSET_arm_R15T]
sewardj59570ff2010-01-01 11:59:33 +0000136
137 /* Are we out of timeslice? If yes, defer to scheduler. */
138 ldr r1, =VG_(dispatch_ctr)
139 ldr r2, [r1]
140 subs r2, r2, #1
141 str r2, [r1]
142 beq counter_is_zero
143
144 /* try a fast lookup in the translation cache */
145 // r0 = next guest, r1,r2,r3 scratch
146 ldr r1, =VG_TT_FAST_MASK // r1 = VG_TT_FAST_MASK
147 and r2, r1, r0, LSR #2 // r2 = entry #
148 ldr r1, =VG_(tt_fast) // r1 = &tt_fast[0]
149 add r1, r1, r2, LSL #3 // r1 = &tt_fast[entry#]
150 ldr r3, [r1, #0] /* .guest */
151 ldr r1, [r1, #4] /* .host */
152 cmp r0, r3
153 bne fast_lookup_failed
154 // r1: live, next-host r8: live, gsp
155 // r2: entry # (but not live)
156 // r0, r3: dead
157
158 /* increment bb profile counter */
159 ldr r0, =VG_(tt_fastN) // r0 = &tt_fastN[0]
160 ldr r0, [r0, r2, LSL #2] // r0 = tt_fast[entry #]
161 ldr r3, [r0] // *r0 ++
162 add r3, r3, #1
163 str r3, [r0]
164
165 /* Found a match. Jump to .host. */
166 blx r1
167 b VG_(run_innerloop__dispatch_profiled)
168 /*NOTREACHED*/
169
170/*----------------------------------------------------*/
171/*--- exit points ---*/
172/*----------------------------------------------------*/
173
174gsp_changed:
sewardj223125d2010-08-22 12:03:45 +0000175 // r0 = next guest addr (R15T), r8 = modified gsp
sewardj59570ff2010-01-01 11:59:33 +0000176 /* Someone messed with the gsp. Have to
177 defer to scheduler to resolve this. dispatch ctr
178 is not yet decremented, so no need to increment. */
sewardj223125d2010-08-22 12:03:45 +0000179 /* R15T is NOT up to date here. First, need to write
180 r0 back to R15T, but without trashing r8 since
sewardj59570ff2010-01-01 11:59:33 +0000181 that holds the value we want to return to the scheduler.
182 Hence use r1 transiently for the guest state pointer. */
183 ldr r1, [sp, #0]
sewardj223125d2010-08-22 12:03:45 +0000184 str r0, [r1, #OFFSET_arm_R15T]
sewardj59570ff2010-01-01 11:59:33 +0000185 mov r0, r8 // "return modified gsp"
186 b run_innerloop_exit
187 /*NOTREACHED*/
188
189counter_is_zero:
sewardj223125d2010-08-22 12:03:45 +0000190 /* R15T is up to date here */
sewardj59570ff2010-01-01 11:59:33 +0000191 /* Back out increment of the dispatch ctr */
192 ldr r1, =VG_(dispatch_ctr)
193 ldr r2, [r1]
194 add r2, r2, #1
195 str r2, [r1]
196 mov r0, #VG_TRC_INNER_COUNTERZERO
197 b run_innerloop_exit
198 /*NOTREACHED*/
199
200fast_lookup_failed:
sewardj223125d2010-08-22 12:03:45 +0000201 /* R15T is up to date here */
sewardj59570ff2010-01-01 11:59:33 +0000202 /* Back out increment of the dispatch ctr */
203 ldr r1, =VG_(dispatch_ctr)
204 ldr r2, [r1]
205 add r2, r2, #1
206 str r2, [r1]
207 mov r0, #VG_TRC_INNER_FASTMISS
208 b run_innerloop_exit
209 /*NOTREACHED*/
210
211/* All exits from the dispatcher go through here. %r0 holds
212 the return value.
213*/
214run_innerloop_exit:
215 /* We're leaving. Check that nobody messed with
216 FPSCR in ways we don't expect. */
217 fmrx r4, fpscr
sewardj223125d2010-08-22 12:03:45 +0000218 bic r4, #0xF8000000 /* mask out NZCV and QC */
219 bic r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
sewardj59570ff2010-01-01 11:59:33 +0000220 cmp r4, #0
221 bne invariant_violation
222 b run_innerloop_exit_REALLY
223
224invariant_violation:
225 mov r0, #VG_TRC_INVARIANT_FAILED
226 b run_innerloop_exit_REALLY
227
228run_innerloop_exit_REALLY:
229 add sp, sp, #8
230 pop {r4, r5, r6, r7, r8, r9, fp, pc}
231
232.size VG_(run_innerloop), .-VG_(run_innerloop)
233
234
235/*------------------------------------------------------------*/
236/*--- ---*/
237/*--- A special dispatcher, for running no-redir ---*/
238/*--- translations. Just runs the given translation once. ---*/
239/*--- ---*/
240/*------------------------------------------------------------*/
241
242/* signature:
243void VG_(run_a_noredir_translation) ( UWord* argblock );
244*/
245
246/* Run a no-redir translation. argblock points to 4 UWords, 2 to carry args
247 and 2 to carry results:
248 0: input: ptr to translation
249 1: input: ptr to guest state
250 2: output: next guest PC
251 3: output: guest state pointer afterwards (== thread return code)
252*/
253.global VG_(run_a_noredir_translation)
254VG_(run_a_noredir_translation):
255 push {r0,r1 /* EABI compliance */, r4-r12, lr}
256 ldr r8, [r0, #4]
257 mov lr, pc
258 ldr pc, [r0, #0]
259
260 pop {r1}
261 str r0, [r1, #8]
262 str r8, [r1, #12]
263 pop {r1/*EABI compliance*/,r4-r12, pc}
264
265.size VG_(run_a_noredir_translation), .-VG_(run_a_noredir_translation)
266
267/* Let the linker know we don't need an executable stack */
268.section .note.GNU-stack,"",%progbits
269
270#endif // defined(VGP_arm_linux)
271
272/*--------------------------------------------------------------------*/
273/*--- end dispatch-arm-linux.S ---*/
274/*--------------------------------------------------------------------*/