]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_dispatch/dispatch-s390x-linux.S
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_dispatch / dispatch-s390x-linux.S
1
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                       dispatch-s390x-linux.S ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright IBM Corp. 2010-2011
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 /* Contributed by Florian Krohm and Christian Borntraeger */
32
33 #include "pub_core_basics_asm.h"
34 #include "pub_core_dispatch_asm.h"
35 #include "pub_core_transtab_asm.h"
36 #include "libvex_guest_offsets.h"
37 #include "libvex_s390x_common.h"
38
39 #if defined(VGA_s390x)
40
41 /*------------------------------------------------------------*/
42 /*---                                                      ---*/
43 /*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
44 /*--- run all translations except no-redir ones.           ---*/
45 /*---                                                      ---*/
46 /*------------------------------------------------------------*/
47
48 /* Convenience definitions for readability */
49 #undef  SP
50 #define SP S390_REGNO_STACK_POINTER
51
52 #undef  LR
53 #define LR S390_REGNO_LINK_REGISTER
54
55 /* Location of valgrind's saved FPC register */
56 #define S390_LOC_SAVED_FPC_V S390_OFFSET_SAVED_FPC_V(SP)
57
58 /* Location of saved guest state pointer */
59 #define S390_LOC_SAVED_GSP S390_OFFSET_SAVED_GSP(SP)
60
61 /*----------------------------------------------------*/
62 /*--- Preamble (set everything up)                 ---*/
63 /*----------------------------------------------------*/
64
65 /* signature:
66 UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
67 */
68
69 .text
70 .align   4
71 .globl VG_(run_innerloop)
72 VG_(run_innerloop):
73         /* r2 holds address of guest_state */
74         /* r3 holds do_profiling (a flag) */
75
76         /* Save gprs   ABI: r6...r13 and r15 */
77         stmg %r6,%r15,48(SP)
78
79         /* New stack frame */
80         aghi SP,-S390_INNERLOOP_FRAME_SIZE
81
82         /* Save fprs:   ABI: f8...f15 */
83         std  %f8,160+0(SP)
84         std  %f9,160+8(SP)
85         std  %f10,160+16(SP)
86         std  %f11,160+24(SP)
87         std  %f12,160+32(SP)
88         std  %f13,160+40(SP)
89         std  %f14,160+48(SP)
90         std  %f15,160+56(SP)
91
92         /* Load address of guest state into guest state register (r13) */
93         lgr  %r13,%r2
94
95         /* Store address of guest state pointer on stack.
96            It will be needed later because upon return from a VEX translation
97            r13 may contain a special value. So the old value will be used to
98            determine whether r13 contains a special value. */
99         stg  %r13,S390_LOC_SAVED_GSP
100
101         /* Save valgrind's FPC on stack so run_innerloop_exit can restore
102            it later . */
103         stfpc S390_LOC_SAVED_FPC_V
104
105         /* Load the FPC the way the client code wants it. I.e. pull the
106            value from the guest state.
107         lfpc OFFSET_s390x_fpc(%r13)
108
109         /* Get the IA from the guest state */
110         lg   %r2,OFFSET_s390x_IA(%r13)
111
112         /* Get VG_(dispatch_ctr) -- a 32-bit value -- and store it in a reg */
113         larl %r6,VG_(dispatch_ctr)
114         l    S390_REGNO_DISPATCH_CTR,0(%r6)
115
116         /* Fall into main loop (the right one) */
117
118         /* r3 = 1 --> do_profiling. We may trash r3 later on. That's OK,
119            because it's a volatile register (does not need to be preserved). */
120         ltgr %r3,%r3
121         je   run_innerloop__dispatch_unprofiled
122         j    run_innerloop__dispatch_profiled
123
124 /*----------------------------------------------------*/
125 /*--- NO-PROFILING (standard) dispatcher           ---*/
126 /*----------------------------------------------------*/
127
128 run_innerloop__dispatch_unprofiled:
129         /* This is the story:
130
131            r2  = IA = next guest address
132            r12 = VG_(dispatch_ctr)
133            r13 = guest state pointer or (upon return from guest code) some
134                  special value
135            r15 = stack pointer (as usual)
136         */
137
138         /* Has the guest state pointer been messed with?  If yes, exit. */
139         cg   %r13,S390_LOC_SAVED_GSP    /* r13 = actual guest state pointer */
140         larl %r8, VG_(tt_fast)
141         jne  gsp_changed
142
143         /* Save the jump address in the guest state */
144         stg  %r2,OFFSET_s390x_IA(%r13)
145
146
147         /* Try a fast lookup in the translation cache:
148            Compute offset (not index) into VT_(tt_fast):
149
150            offset = VG_TT_FAST_HASH(addr) * sizeof(FastCacheEntry)
151
152            with VG_TT_FAST_HASH(addr) == (addr >> 1) & VG_TT_FAST_MASK
153            and  sizeof(FastCacheEntry) == 16
154
155            offset = ((addr >> 1) & VG_TT_FAST_MASK) << 4
156         */
157         lghi %r5,VG_TT_FAST_MASK
158         srlg %r7, %r2,1              /* next guest addr >> 1*/
159         ngr  %r7,%r5
160         sllg %r7,%r7,4
161
162         /* Set the return address to the beginning of the loop here to
163            have some instruction between setting r7 and using it as an
164            address */
165         larl LR,run_innerloop__dispatch_unprofiled
166
167         /* Are we out of timeslice?  If yes, defer to scheduler. */
168         ahi  S390_REGNO_DISPATCH_CTR,-1
169         jz   counter_is_zero
170
171
172         lg   %r10, 0(%r8,%r7)      /* .guest */
173         lg   %r11, 8(%r8,%r7)      /* .host */
174         cgr  %r2, %r10
175         jne  fast_lookup_failed
176
177         /* Found a match.  Call .host.
178            r11 is an address. There we will find the instrumented client code.
179            That code may modify the guest state register r13. The client code
180            will return to the beginning of this loop start by issuing br LR.
181            We can simply branch to the host code */
182         br %r11
183
184
185 /*----------------------------------------------------*/
186 /*--- PROFILING dispatcher (can be much slower)    ---*/
187 /*----------------------------------------------------*/
188
189 run_innerloop__dispatch_profiled:
190
191         /* Has the guest state pointer been messed with?  If yes, exit. */
192         cg   %r13,S390_LOC_SAVED_GSP    /* r13 = actual guest state pointer */
193         larl %r8, VG_(tt_fast)
194         jne  gsp_changed
195
196         /* Save the jump address in the guest state */
197         stg  %r2,OFFSET_s390x_IA(%r13)
198
199         /* Try a fast lookup in the translation cache:
200            Compute offset (not index) into VT_(tt_fast):
201
202            offset = VG_TT_FAST_HASH(addr) * sizeof(FastCacheEntry)
203
204            with VG_TT_FAST_HASH(addr) == (addr >> 1) & VG_TT_FAST_MASK
205            and  sizeof(FastCacheEntry) == 16
206
207            offset = ((addr >> 1) & VG_TT_FAST_MASK) << 4
208         */
209         lghi %r5,VG_TT_FAST_MASK
210         srlg %r7,%r2,1              /* next guest addr >> 1*/
211         ngr  %r7,%r5
212         sllg %r7,%r7,4
213
214         /* Set the return address to the beginning of the loop here to
215            have some instruction between setting r7 and using it as an
216            address */
217         larl LR,run_innerloop__dispatch_profiled
218
219         /* Are we out of timeslice?  If yes, defer to scheduler. */
220         ahi  S390_REGNO_DISPATCH_CTR,-1
221         jz   counter_is_zero
222
223         lg   %r10, 0(%r8,%r7)      /* .guest */
224         lg   %r11, 8(%r8,%r7)      /* .host */
225         cgr  %r2, %r10
226         jne  fast_lookup_failed
227
228         /* sizeof(FastCacheEntry) == 16, sizeof(*UInt)==8 */
229         srlg %r7,%r7,1
230
231         /* we got a hit: VG_(tt_fastN) is guaranteed to point to count */
232         larl %r8, VG_(tt_fastN)
233
234         /* increment bb profile counter */
235         lg   %r9,0(%r8,%r7)
236         l    %r10,0(%r9)
237         ahi  %r10,1
238         st   %r10,0(%r9)
239
240         /* Found a match.  Call .host.
241            r11 is an address. There we will find the instrumented client code.
242            That code may modify the guest state register r13. The client code
243            will return to the beginning of this loop start by issuing br LR.
244            We can simply branch to the host code */
245         br %r11
246
247 /*----------------------------------------------------*/
248 /*--- exit points                                  ---*/
249 /*----------------------------------------------------*/
250
251 gsp_changed:
252         /* Someone messed with the gsp (in r13).  Have to
253            defer to scheduler to resolve this.  The register
254            holding VG_(dispatch_ctr) is not yet decremented,
255            so no need to increment. */
256
257         /* Update the IA in the guest state */
258         lg  %r6,S390_LOC_SAVED_GSP       /* r6 = original guest state pointer */
259         stg %r2,OFFSET_s390x_IA(%r6)
260
261         /* Return the special guest state pointer value */
262         lgr %r2, %r13
263         j   run_innerloop_exit
264
265
266 counter_is_zero:
267         /* IA is up to date */
268
269         /* Back out decrement of the dispatch counter */
270         ahi S390_REGNO_DISPATCH_CTR,1
271
272         /* Set return value for the scheduler */
273         lghi %r2,VG_TRC_INNER_COUNTERZERO
274         j    run_innerloop_exit
275
276
277 fast_lookup_failed:
278         /* IA is up to date */
279
280         /* Back out decrement of the dispatch counter */
281         ahi S390_REGNO_DISPATCH_CTR,1
282
283         /* Set return value for the scheduler */
284         lghi %r2,VG_TRC_INNER_FASTMISS
285         j    run_innerloop_exit
286
287
288         /* All exits from the dispatcher go through here.
289            When we come here r2 holds the return value. */
290 run_innerloop_exit:
291
292         /* Restore valgrind's FPC, as client code may have changed it. */
293         lfpc S390_LOC_SAVED_FPC_V
294
295         /* Write ctr to VG_(dispatch_ctr) (=32bit value) */
296         larl %r6,VG_(dispatch_ctr)
297         st   S390_REGNO_DISPATCH_CTR,0(%r6)
298
299         /* Restore callee-saved registers... */
300
301         /* Floating-point regs */
302         ld  %f8,160+0(SP)
303         ld  %f9,160+8(SP)
304         ld  %f10,160+16(SP)
305         ld  %f11,160+24(SP)
306         ld  %f12,160+32(SP)
307         ld  %f13,160+40(SP)
308         ld  %f14,160+48(SP)
309         ld  %f15,160+56(SP)
310
311         /* Remove atack frame */
312         aghi SP,S390_INNERLOOP_FRAME_SIZE
313
314         /* General-purpose regs. This also restores the original link
315            register (r14) and stack pointer (r15). */
316         lmg %r6,%r15,48(SP)
317
318         /* Return */
319         br  LR
320
321 /*------------------------------------------------------------*/
322 /*---                                                      ---*/
323 /*--- A special dispatcher, for running no-redir           ---*/
324 /*--- translations.  Just runs the given translation once. ---*/
325 /*---                                                      ---*/
326 /*------------------------------------------------------------*/
327
328 /* signature:
329 void VG_(run_a_noredir_translation) ( UWord* argblock );
330 */
331
332 /* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
333    and 2 to carry results:
334       0: input:  ptr to translation
335       1: input:  ptr to guest state
336       2: output: next guest PC
337       3: output: guest state pointer afterwards (== thread return code)
338 */
339 .text
340 .align   4
341 .globl VG_(run_a_noredir_translation)
342 VG_(run_a_noredir_translation):
343         stmg %r6,%r15,48(SP)
344         aghi SP,-S390_INNERLOOP_FRAME_SIZE
345         std  %f8,160+0(SP)
346         std  %f9,160+8(SP)
347         std  %f10,160+16(SP)
348         std  %f11,160+24(SP)
349         std  %f12,160+32(SP)
350         std  %f13,160+40(SP)
351         std  %f14,160+48(SP)
352         std  %f15,160+56(SP)
353
354         /* Load address of guest state into guest state register (r13) */
355         lg   %r13,8(%r2)
356
357         /* Get the IA */
358         lg   %r11,0(%r2)
359
360         /* save r2 (argblock) as it is clobbered */
361         stg  %r2,160+64(SP)
362
363         /* the call itself */
364         basr LR,%r11
365
366         /* restore argblock */
367         lg   %r1,160+64(SP)
368         /* save the next guest PC */
369         stg  %r2,16(%r1)
370
371         /* save the guest state */
372         stg  %r13,24(%r1)
373
374         /* Restore Floating-point regs */
375         ld  %f8,160+0(SP)
376         ld  %f9,160+8(SP)
377         ld  %f10,160+16(SP)
378         ld  %f11,160+24(SP)
379         ld  %f12,160+32(SP)
380         ld  %f13,160+40(SP)
381         ld  %f14,160+48(SP)
382         ld  %f15,160+56(SP)
383
384         aghi SP,S390_INNERLOOP_FRAME_SIZE
385
386         lmg %r6,%r15,48(SP)
387         br  %r14
388
389
390 /* Let the linker know we don't need an executable stack */
391 .section .note.GNU-stack,"",@progbits
392
393 #endif /* VGA_s390x */
394
395 /*--------------------------------------------------------------------*/
396 /*--- end                                   dispatch-s390x-linux.S ---*/
397 /*--------------------------------------------------------------------*/