FreeBSD syscall: add wrapper for kcmp
[valgrind.git] / coregrind / m_dispatch / dispatch-arm-linux.S
blob40629017c8bbcacfe8d9669dd027815c9295790e
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                         dispatch-arm-linux.S ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
11   Copyright (C) 2008-2017 Evan Geller
12      gaze@bea.ms
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 #include "pub_core_basics_asm.h"
32 #if defined(VGP_arm_linux)
33         .fpu vfp
35 #include "pub_core_dispatch_asm.h"
36 #include "pub_core_transtab_asm.h"
37 #include "libvex_guest_offsets.h"       /* for OFFSET_arm_R* */
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 /*----------------------------------------------------*/
49 /*--- Entry and preamble (set everything up)       ---*/
50 /*----------------------------------------------------*/
52 /* signature:
53 void VG_(disp_run_translations)( UWord* two_words,
54                                  void*  guest_state, 
55                                  Addr   host_addr );
57 .text
58 .global VG_(disp_run_translations)
59 VG_(disp_run_translations):
60         /* r0  holds two_words
61            r1  holds guest_state
62            r2  holds host_addr
63         */
64         /* The number of regs in this list needs to be even, in
65            order to keep the stack 8-aligned. */
66         push {r0, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
68         /* set FPSCR to vex-required default value */
69         mov  r4, #0
70         fmxr fpscr, r4
72         /* Set up the guest state pointer */
73         mov r8, r1
75         /* and jump into the code cache.  Chained translations in
76            the code cache run, until for whatever reason, they can't
77            continue.  When that happens, the translation in question
78            will jump (or call) to one of the continuation points
79            VG_(cp_...) below. */
80         bx r2
81         /* NOTREACHED */
82         
83 /*----------------------------------------------------*/
84 /*--- Postamble and exit.                          ---*/
85 /*----------------------------------------------------*/
87 postamble:
88         /* At this point, r1 and r2 contain two
89            words to be returned to the caller.  r1
90            holds a TRC value, and r2 optionally may
91            hold another word (for CHAIN_ME exits, the
92            address of the place to patch.) */
94         /* We're leaving.  Check that nobody messed with
95            FPSCR in ways we don't expect. */
96         fmrx r4, fpscr
97         bic  r4, #0xF8000000 /* mask out NZCV and QC */
98         bic  r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
99         cmp  r4, #0
100         beq  remove_frame /* we're OK */
101         /* otherwise we have an invariant violation */
102         movw r1, #VG_TRC_INVARIANT_FAILED
103         movw r2, #0
104         /* fall through */
106 remove_frame:
107         /* Restore int regs, including importantly r0 (two_words) */
108         pop {r0, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}     
109         /* Stash return values */
110         str  r1, [r0, #0]
111         str  r2, [r0, #4]
112         bx   lr
114 /*----------------------------------------------------*/
115 /*--- Continuation points                          ---*/
116 /*----------------------------------------------------*/
118 /* ------ Chain me to slow entry point ------ */
119 .global VG_(disp_cp_chain_me_to_slowEP)
120 VG_(disp_cp_chain_me_to_slowEP):
121         /* We got called.  The return address indicates
122            where the patching needs to happen.  Collect
123            the return address and, exit back to C land,
124            handing the caller the pair (Chain_me_S, RA) */
125         mov  r1, #VG_TRC_CHAIN_ME_TO_SLOW_EP
126         mov  r2, lr
127         /* 4 = movw r12, lo16(disp_cp_chain_me_to_slowEP)
128            4 = movt r12, hi16(disp_cp_chain_me_to_slowEP)
129            4 = blx  r12 */
130         sub  r2, r2, #4+4+4
131         b    postamble
133 /* ------ Chain me to fast entry point ------ */
134 .global VG_(disp_cp_chain_me_to_fastEP)
135 VG_(disp_cp_chain_me_to_fastEP):
136         /* We got called.  The return address indicates
137            where the patching needs to happen.  Collect
138            the return address and, exit back to C land,
139            handing the caller the pair (Chain_me_F, RA) */
140         mov  r1, #VG_TRC_CHAIN_ME_TO_FAST_EP
141         mov  r2, lr
142         /* 4 = movw r12, lo16(disp_cp_chain_me_to_fastEP)
143            4 = movt r12, hi16(disp_cp_chain_me_to_fastEP)
144            4 = blx  r12 */
145         sub  r2, r2, #4+4+4
146         b    postamble
148 /* ------ Indirect but boring jump ------ */
149 .global VG_(disp_cp_xindir)
150 VG_(disp_cp_xindir):
151         /* Where are we going? */
152         ldr  r0, [r8, #OFFSET_arm_R15T]
154         /* stats only */
155         movw r4, #:lower16:VG_(stats__n_xIndirs_32)
156         movt r4, #:upper16:VG_(stats__n_xIndirs_32)
157         ldr  r5, [r4, #0]
158         add  r5, r5, #1
159         str  r5, [r4, #0]
161         // LIVE: r8 (guest state ptr), r0 (guest address to go to).
162         // We use 6 temporaries:
163         //   r6 (to point at the relevant FastCacheSet),
164         //   r1, r2, r3 (scratch, for swapping entries within a set)
165         //   r4, r5 (other scratch)
167         /* Try a fast lookup in the translation cache.  This is pretty much
168            a handcoded version of VG_(lookupInFastCache). */
170         // Compute r6 = VG_TT_FAST_HASH(guest)
171         lsr  r6, r0, #1                       // g1 = guest >> 1
172         eor  r6, r6, r6, LSR #VG_TT_FAST_BITS // (g1 >> VG_TT_FAST_BITS) ^ g1
173         ubfx r6, r6, #0, #VG_TT_FAST_BITS     // setNo
174         
175         // Compute r6 = &VG_(tt_fast)[r6]
176         movw r4, #:lower16:VG_(tt_fast)
177         movt r4, #:upper16:VG_(tt_fast)
178         add  r6, r4, r6, LSL #VG_FAST_CACHE_SET_BITS // &VG_(tt_fast)[setNo]
180         // LIVE: r8 (guest state ptr), r0 (guest addr), r6 (cache set)
181         // try way 0
182         ldr  r4, [r6, #FCS_g0]   // .guest0
183         ldr  r5, [r6, #FCS_h0]   // .host0
184         cmp  r4, r0   // cmp against .guest0
185         bne  1f
186         // hit at way 0
187         // goto .host0
188         bx   r5
189         /*NOTREACHED*/
191 1:      // try way 1
192         ldr  r4, [r6, #FCS_g1]
193         cmp  r4, r0   // cmp against .guest1
194         bne  2f
195         // hit at way 1; swap upwards
196         ldr  r1, [r6, #FCS_g0]   // r1 = old .guest0
197         ldr  r2, [r6, #FCS_h0]   // r2 = old .host0
198         ldr  r3, [r6, #FCS_h1]   // r3 = old .host1
199         str  r0, [r6, #FCS_g0]   // new .guest0 = guest
200         str  r3, [r6, #FCS_h0]   // new .host0 = old .host1
201         str  r1, [r6, #FCS_g1]   // new .guest1 = old .guest0
202         str  r2, [r6, #FCS_h1]   // new .host1 = old .host0
203         // stats only
204         movw r4, #:lower16:VG_(stats__n_xIndir_hits1_32)
205         movt r4, #:upper16:VG_(stats__n_xIndir_hits1_32)
206         ldr  r5, [r4, #0]
207         add  r5, r5, #1
208         str  r5, [r4, #0]
209         // goto old .host1 a.k.a. new .host0
210         bx   r3
211         /*NOTREACHED*/
213 2:      // try way 2
214         ldr  r4, [r6, #FCS_g2]
215         cmp  r4, r0   // cmp against .guest2
216         bne  3f
217         // hit at way 2; swap upwards
218         ldr  r1, [r6, #FCS_g1]
219         ldr  r2, [r6, #FCS_h1]
220         ldr  r3, [r6, #FCS_h2]
221         str  r0, [r6, #FCS_g1]
222         str  r3, [r6, #FCS_h1]
223         str  r1, [r6, #FCS_g2]
224         str  r2, [r6, #FCS_h2]
225         // stats only
226         movw r4, #:lower16:VG_(stats__n_xIndir_hits2_32)
227         movt r4, #:upper16:VG_(stats__n_xIndir_hits2_32)
228         ldr  r5, [r4, #0]
229         add  r5, r5, #1
230         str  r5, [r4, #0]
231         // goto old .host2 a.k.a. new .host1
232         bx   r3
233         /*NOTREACHED*/
235 3:      // try way 3
236         ldr  r4, [r6, #FCS_g3]
237         cmp  r4, r0   // cmp against .guest3
238         bne  4f
239         // hit at way 3; swap upwards
240         ldr  r1, [r6, #FCS_g2]
241         ldr  r2, [r6, #FCS_h2]
242         ldr  r3, [r6, #FCS_h3]
243         str  r0, [r6, #FCS_g2]
244         str  r3, [r6, #FCS_h2]
245         str  r1, [r6, #FCS_g3]
246         str  r2, [r6, #FCS_h3]
247         // stats only
248         movw r4, #:lower16:VG_(stats__n_xIndir_hits3_32)
249         movt r4, #:upper16:VG_(stats__n_xIndir_hits3_32)
250         ldr  r5, [r4, #0]
251         add  r5, r5, #1
252         str  r5, [r4, #0]
253         // goto old .host3 a.k.a. new .host2
254         bx   r3
255         /*NOTREACHED*/
257 4:      // fast lookup failed
258         movw r4, #:lower16:VG_(stats__n_xIndir_misses_32)
259         movt r4, #:upper16:VG_(stats__n_xIndir_misses_32)
260         ldr  r5, [r4, #0]
261         add  r5, r5, #1
262         str  r5, [r4, #0]
264         mov  r1, #VG_TRC_INNER_FASTMISS
265         mov  r2, #0
266         b    postamble
268 /* ------ Assisted jump ------ */
269 .global VG_(disp_cp_xassisted)
270 VG_(disp_cp_xassisted):
271         /* r8 contains the TRC */
272         mov  r1, r8
273         mov  r2, #0
274         b    postamble
276 /* ------ Event check failed ------ */
277 .global VG_(disp_cp_evcheck_fail)
278 VG_(disp_cp_evcheck_fail):
279         mov  r1, #VG_TRC_INNER_COUNTERZERO
280         mov  r2, #0
281         b    postamble
284 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
286 #endif // defined(VGP_arm_linux)
288 /* Let the linker know we don't need an executable stack */
289 MARK_STACK_NO_EXEC
291 /*--------------------------------------------------------------------*/
292 /*--- end                                     dispatch-arm-linux.S ---*/
293 /*--------------------------------------------------------------------*/