]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_dispatch/dispatch-arm-linux.S
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_dispatch / dispatch-arm-linux.S
1 /*--------------------------------------------------------------------*/
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
10   Copyright (C) 2008-2010 Evan Geller
11      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)
32         .fpu vfp
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_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:
52 UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
53 */
54 .text
55 .globl VG_(run_innerloop)
56 VG_(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
66         ldr r0, [r8, #OFFSET_arm_R15T]
67         
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)
79 VG_(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 */
90         str  r0, [r8, #OFFSET_arm_R15T]
91
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 #1         // 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)
124 VG_(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 */
135         str  r0, [r8, #OFFSET_arm_R15T]
136
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 #1         // 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
174 gsp_changed:
175         // r0 = next guest addr (R15T), r8 = modified gsp
176         /* 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. */
179         /* R15T is NOT up to date here.  First, need to write
180            r0 back to R15T, but without trashing r8 since
181            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]
184         str r0, [r1, #OFFSET_arm_R15T]
185         mov r0, r8      // "return modified gsp"
186         b run_innerloop_exit
187         /*NOTREACHED*/
188
189 counter_is_zero:
190         /* R15T is up to date here */
191         /* 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         
200 fast_lookup_failed:
201         /* R15T is up to date here */
202         /* 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 */
214 run_innerloop_exit:
215         /* We're leaving.  Check that nobody messed with
216            FPSCR in ways we don't expect. */
217         fmrx r4, fpscr
218         bic  r4, #0xF8000000 /* mask out NZCV and QC */
219         bic  r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
220         cmp  r4, #0
221         bne  invariant_violation
222         b    run_innerloop_exit_REALLY
223
224 invariant_violation:
225         mov  r0, #VG_TRC_INVARIANT_FAILED
226         b    run_innerloop_exit_REALLY
227
228 run_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:
243 void 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)
254 VG_(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 /*--------------------------------------------------------------------*/