FreeBSD syscall: add wrapper for kcmp
[valgrind.git] / coregrind / m_dispatch / dispatch-s390x-linux.S
blob4acc5ba2fb5fa9fe955334bd14a8621b94a3c128
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                       dispatch-s390x-linux.S ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
11   Copyright IBM Corp. 2010-2017
12   Copyright (C) 2011-2017, Florian Krohm (britzel@acm.org)
13         
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.
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.
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, see <http://www.gnu.org/licenses/>.
27   The GNU General Public License is contained in the file COPYING.
30 /* Contributed by Florian Krohm and Christian Borntraeger */
32 #include "pub_core_basics_asm.h"
33 #include "pub_core_dispatch_asm.h"
34 #include "pub_core_transtab_asm.h"
35 #include "libvex_guest_offsets.h"
36 #include "libvex_s390x_common.h"
38 #if defined(VGA_s390x)
40 /*------------------------------------------------------------*/
41 /*---                                                      ---*/
42 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
43 /*--- used to run all translations,                        ---*/
44 /*--- including no-redir ones.                             ---*/
45 /*---                                                      ---*/
46 /*------------------------------------------------------------*/
48 /* Convenience definitions for readability */
49 #undef  SP
50 #define SP S390_REGNO_STACK_POINTER
52 #undef  LR
53 #define LR S390_REGNO_LINK_REGISTER
55 /* Location of valgrind's saved FPC register */
56 #define S390_LOC_SAVED_FPC_V S390_OFFSET_SAVED_FPC_V(SP)
58 /* Location of saved R2 register */
59 #define S390_LOC_SAVED_R2 S390_OFFSET_SAVED_R2(SP)
62 /*----------------------------------------------------*/
63 /*--- Entry and preamble (set everything up)       ---*/
64 /*----------------------------------------------------*/
66 /* signature:
67 void VG_(disp_run_translations)( UWord* two_words,
68                                  void*  guest_state, 
69                                  Addr   host_addr );
71         Return results are placed in two_words:
72         
73         two_words[0] is set to the TRC
74         two_words[1] is set to the address to patch (in case two_words[0] is
75                      VG_TRC_CHAIN_ME_TO_{SLOW,FAST}_EP). Otherwise, it is 0.
77         .text
78         .align   4
79         .globl   VG_(disp_run_translations)
80         .type    VG_(disp_run_translations), @function
81 VG_(disp_run_translations):
83         /* r2 holds two_words */
84         /* r3 holds pointer to guest_state */
85         /* r4 holds host_addr, i.e. the address of the translation to run */
87         /* Save gprs   ABI: r6...r13 and r15 */
88         stmg  %r6,%r15,48(SP)
90         /* New stack frame */
91         aghi  SP,-S390_INNERLOOP_FRAME_SIZE
93         /* Save fprs:   ABI: f8...f15 */
94         std   %f8,160+0(SP)
95         std   %f9,160+8(SP)
96         std   %f10,160+16(SP)
97         std   %f11,160+24(SP)
98         std   %f12,160+32(SP)
99         std   %f13,160+40(SP)
100         std   %f14,160+48(SP)
101         std   %f15,160+56(SP)
103         /* Load address of guest state into guest state register (r13) */
104         lgr   %r13,%r3
106         /* Save R2 on stack. In postamble it will be restored such that the
107            return values can be written */
108         stg   %r2,S390_LOC_SAVED_R2
109         
110         /* Save valgrind's FPC on stack so postamble can restore
111            it later . */
112         stfpc S390_LOC_SAVED_FPC_V
114         /* Load the FPC the way the client code wants it. I.e. pull the
115            value from the guest state. */
116         lfpc  OFFSET_s390x_fpc(%r13)
118         /* Jump into the code cache.  Chained translations in
119            the code cache run, until for whatever reason, they can't
120            continue.  When that happens, the translation in question
121            will jump (or call) to one of the continuation points
122            VG_(cp_...) below. */
123         br    %r4
126 /*----------------------------------------------------*/
127 /*--- Postamble and return to C code.              ---*/
128 /*----------------------------------------------------*/
130 postamble:
131         /* At this point, %r0 and %r1 contain two
132            words to be returned to the caller.  %r0
133            holds a TRC value, and %r1 optionally may
134            hold another word (for CHAIN_ME exits, the
135            address of the place to patch.) */
137         /* We're leaving. AMD has some code here to check invariants.
138            We don't have (need) that, as we save and restore the FPC register
139            whenever we switch between valgrind proper to client code. */
141         /* Restore valgrind's FPC, as client code may have changed it. */
142         lfpc S390_LOC_SAVED_FPC_V
144         /* Restore %r2 from stack; holds address of two_words */
145         lg   %r2,S390_LOC_SAVED_R2
147         stg  %r0,0(%r2)         /* Store %r0 to two_words[0] */
148         stg  %r1,8(%r2)         /* Store %r1 to two_words[1] */
149         
150         /* Restore callee-saved registers... */
152         /* Floating-point regs */
153         ld   %f8,160+0(SP)
154         ld   %f9,160+8(SP)
155         ld   %f10,160+16(SP)
156         ld   %f11,160+24(SP)
157         ld   %f12,160+32(SP)
158         ld   %f13,160+40(SP)
159         ld   %f14,160+48(SP)
160         ld   %f15,160+56(SP)
162         /* Remove stack frame */
163         aghi SP,S390_INNERLOOP_FRAME_SIZE
165         /* General-purpose regs. This also restores the original link
166            register (r14) and stack pointer (r15). */
167         lmg  %r6,%r15,48(SP)
169         /* Return */
170         br   LR
171         
172         
173 /*----------------------------------------------------*/
174 /*--- Continuation points                          ---*/
175 /*----------------------------------------------------*/
177 /* ------ Chain me to slow entry point ------ */
178         .global VG_(disp_cp_chain_me_to_slowEP)
179 VG_(disp_cp_chain_me_to_slowEP):
180         /* When we come here %r1 contains the address of the place to patch.
181            The return values (TRC, address-to-patch) are stored here in
182            %r0 and %r1, respectively */
183         lghi    %r0,VG_TRC_CHAIN_ME_TO_SLOW_EP
184         j       postamble
187 /* ------ Chain me to fast entry point ------ */
188         .global VG_(disp_cp_chain_me_to_fastEP)
189 VG_(disp_cp_chain_me_to_fastEP):
190         /* Identical to VG_(disp_cp_chain_me_to_slowEP), except value of %r0. */
191         lghi    %r0,VG_TRC_CHAIN_ME_TO_FAST_EP
192         j       postamble
195 /* ------ Indirect but boring jump ------ */
196         .global VG_(disp_cp_xindir)
197 VG_(disp_cp_xindir):
198         /* Where are we going? */
199         lg      %r6, OFFSET_s390x_IA(%r13)   // "guest"
201         /* stats only */
202         larl    %r11, VG_(stats__n_xIndirs_32)
203         l       %r12, 0(%r11)
204         ahi     %r12, 1
205         st      %r12, 0(%r11)
207         // LIVE: r13 (guest state ptr), r6 (guest address to go to).
208         // We use 6 temporaries:
209         //   r7 (to point at the relevant FastCacheSet),
210         //   r8, r9, r10 (scratch, for swapping entries within a set)
211         //   r11, r12 (other scratch)
213         /* Try a fast lookup in the translation cache.  This is pretty much
214            a handcoded version of VG_(lookupInFastCache). */
216         // Compute %r7 = VG_TT_FAST_HASH(guest)
217         srlg    %r7, %r6, 1                     // g1 = guest >> 1
218         srlg    %r8, %r6, (VG_TT_FAST_BITS + 1) // (g1 >> VG_TT_FAST_BITS)
219         xgr     %r7, %r8                        // (g1 >> VG_TT_FAST_BITS) ^ g1
220         llill   %r8, VG_TT_FAST_MASK & 0xffff
221 #       if ((VG_TT_FAST_MASK & 0xffff0000) >> 16 != 0)
222         iilh    %r8, (VG_TT_FAST_MASK & 0xffff0000) >> 16
223 #       endif
224         ngr     %r7, %r8                        // setNo
226         // Compute %r7 = &VG_(tt_fast)[%r7]
227         sllg    %r7,%r7, VG_FAST_CACHE_SET_BITS // setNo * sizeof(FastCacheSet)
228         larl    %r8, VG_(tt_fast)             // &VG_(tt_fast)[0]
229         agr     %r7, %r8                      // &VG_(tt_fast)[setNo]
231         // LIVE: %r13 (guest state ptr), %r6 (guest addr), %r7 (cache set)
232         // try way 0
233         cg      %r6, FCS_g0(%r7)   // cmp against .guest0
234         lg      %r8, FCS_h0(%r7)
235         jne     1f
236         // hit at way 0
237         // goto .host0
238         br      %r8
239         /*NOTREACHED*/
240         .long   0
242 1:      // try way 1
243         cg      %r6, FCS_g1(%r7)   // cmp against .guest1
244         jne     2f
245         // hit at way 1; swap upwards
246         lg      %r8,  FCS_g0(%r7)  // r8  = old .guest0
247         lg      %r9,  FCS_h0(%r7)  // r9  = old .host0
248         lg      %r10, FCS_h1(%r7)  // r10 = old .host1
249         stg     %r6,  FCS_g0(%r7)  // new .guest0 = guest
250         stg     %r10, FCS_h0(%r7)  // new .host0 = old .host1
251         stg     %r8,  FCS_g1(%r7)  // new .guest1 = old .guest0
252         stg     %r9,  FCS_h1(%r7)  // new .host1 = old .host0
253         // stats only
254         larl    %r11, VG_(stats__n_xIndir_hits1_32)
255         l       %r12, 0(%r11)
256         ahi     %r12, 1
257         st      %r12, 0(%r11)
258         // goto old .host1 a.k.a. new .host0
259         br      %r10
260         /*NOTREACHED*/
261         .long 0
263 2:      // try way 2
264         cg      %r6, FCS_g2(%r7)   // cmp against .guest2
265         jne     3f
266         lg      %r8,  FCS_g1(%r7)
267         lg      %r9,  FCS_h1(%r7)
268         lg      %r10, FCS_h2(%r7)
269         stg     %r6,  FCS_g1(%r7)
270         stg     %r10, FCS_h1(%r7)
271         stg     %r8,  FCS_g2(%r7)
272         stg     %r9,  FCS_h2(%r7)
273         // stats only
274         larl    %r11, VG_(stats__n_xIndir_hits2_32)
275         l       %r12, 0(%r11)
276         ahi     %r12, 1
277         st      %r12, 0(%r11)
278         // goto old .host2 a.k.a. new .host1
279         br      %r10
280         /*NOTREACHED*/
281         .long 0
283 3:      // try way 3
284         cg      %r6, FCS_g3(%r7)   // cmp against .guest3
285         jne     4f
286         // hit at way 3; swap upwards
287         lg      %r8,  FCS_g2(%r7)
288         lg      %r9,  FCS_h2(%r7)
289         lg      %r10, FCS_h3(%r7)
290         stg     %r6,  FCS_g2(%r7)
291         stg     %r10, FCS_h2(%r7)
292         stg     %r8,  FCS_g3(%r7)
293         stg     %r9,  FCS_h3(%r7)
294         // stats only
295         larl    %r11, VG_(stats__n_xIndir_hits3_32)
296         l       %r12, 0(%r11)
297         ahi     %r12, 1
298         st      %r12, 0(%r11)
299         // goto old .host3 a.k.a. new .host2
300         br      %r10
301         .long 0
303 4:      // fast lookup failed
304         larl    %r11, VG_(stats__n_xIndir_misses_32)
305         l       %r12, 0(%r11)
306         ahi     %r12, 1
307         st      %r12, 0(%r11)
309         lghi    %r0, VG_TRC_INNER_FASTMISS
310         lghi    %r1, 0
311         j       postamble
312         /*NOTREACHED*/
314         
315 /* ------ Assisted jump ------ */
316         .global VG_(disp_cp_xassisted)
317 VG_(disp_cp_xassisted):
318         /* guest-state-pointer contains the TRC. Put the value into the
319            return register */
320         lgr     %r0,%r13
321         lghi    %r1,0
322         j       postamble
325 /* ------ Event check failed ------ */
326         .global VG_(disp_cp_evcheck_fail)
327 VG_(disp_cp_evcheck_fail):
328         lghi    %r0,VG_TRC_INNER_COUNTERZERO
329         lghi    %r1,0
330         j       postamble
333         .size VG_(disp_run_translations), .-VG_(disp_run_translations)
335 #endif /* VGA_s390x */
337 /* Let the linker know we don't need an executable stack */
338 MARK_STACK_NO_EXEC
340 /*--------------------------------------------------------------------*/
341 /*--- end                                   dispatch-s390x-linux.S ---*/
342 /*--------------------------------------------------------------------*/