FreeBSD Helgrind: turn off check for locks held on exit for FreeBSD 14.2
[valgrind.git] / coregrind / m_dispatch / dispatch-arm64-freebsd.S
blobfcc222d498c4e3cb73c0791ba594f80318b953cc
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                     dispatch-arm64-freebsd.S ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
11   Copyright (C) 2024 Paul Floyd
12       pjfloyd@wanadoo.fr
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_arm64_freebsd)
34 #include "pub_core_dispatch_asm.h"
35 #include "pub_core_transtab_asm.h"
36 #include "libvex_guest_offsets.h"       /* for OFFSET_arm_R* */
39 /*------------------------------------------------------------*/
40 /*---                                                      ---*/
41 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
42 /*--- used to run all translations,                        ---*/
43 /*--- including no-redir ones.                             ---*/
44 /*---                                                      ---*/
45 /*------------------------------------------------------------*/
47 /*----------------------------------------------------*/
48 /*--- Entry and preamble (set everything up)       ---*/
49 /*----------------------------------------------------*/
51 /* signature:
52 void VG_(disp_run_translations)( UWord* two_words,
53                                  void*  guest_state,
54                                  Addr   host_addr );
56 .text
57 .global VG_(disp_run_translations)
58 VG_(disp_run_translations):
59         /* x0  holds two_words
60            x1  holds guest_state
61            x2  holds host_addr
62         */
63         /* Push the callee-saved registers.  Unclear if x19/x20 are
64            callee-saved, but be on the safe side.  Note this sequence
65            maintains 16-alignment of sp.  Also save x0 since it will
66            be needed in the postamble. */
67         stp  x29, x30, [sp, #-16]!
68         stp  x27, x28, [sp, #-16]!
69         stp  x25, x26, [sp, #-16]!
70         stp  x23, x24, [sp, #-16]!
71         stp  x21, x22, [sp, #-16]!
72         stp  x19, x20, [sp, #-16]!
73         stp  x0,  xzr, [sp, #-16]!
75         /* set FPSCR to vex-required default value */
76         // FIXME
77         // mov  r4, #0
78         // fmxr fpscr, r4
80         /* Set up the guest state pointer */
81         mov x21, x1
83         /* and jump into the code cache.  Chained translations in
84            the code cache run, until for whatever reason, they can't
85            continue.  When that happens, the translation in question
86            will jump (or call) to one of the continuation points
87            VG_(cp_...) below. */
88         br x2
89         /* NOTREACHED */
91 /*----------------------------------------------------*/
92 /*--- Postamble and exit.                          ---*/
93 /*----------------------------------------------------*/
95 postamble:
96         /* At this point, r1 and r2 contain two
97            words to be returned to the caller.  r1
98            holds a TRC value, and r2 optionally may
99            hold another word (for CHAIN_ME exits, the
100            address of the place to patch.) */
102         /* We're leaving.  Check that nobody messed with
103            FPSCR in ways we don't expect. */
104         // FIXME
105         // fmrx r4, fpscr
106         // bic  r4, #0xF8000000 /* mask out NZCV and QC */
107         // bic  r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
108         // cmp  r4, #0
109         // beq  remove_frame /* we're OK */
110         /* otherwise we have an invariant violation */
111         // movw r1, #VG_TRC_INVARIANT_FAILED
112         // movw r2, #0
113         /* fall through */
115 remove_frame:
116         /* Restore int regs, including importantly x0 (two_words),
117            but not x1 */
118         ldp  x0,  xzr, [sp], #16
119         ldp  x19, x20, [sp], #16
120         ldp  x21, x22, [sp], #16
121         ldp  x23, x24, [sp], #16
122         ldp  x25, x26, [sp], #16
123         ldp  x27, x28, [sp], #16
124         ldp  x29, x30, [sp], #16
126         /* Stash return values */
127         str  x1, [x0, #0]
128         str  x2, [x0, #8]
129         ret
131 /*----------------------------------------------------*/
132 /*--- Continuation points                          ---*/
133 /*----------------------------------------------------*/
135 /* ------ Chain me to slow entry point ------ */
136 .global VG_(disp_cp_chain_me_to_slowEP)
137 VG_(disp_cp_chain_me_to_slowEP):
138         /* We got called.  The return address indicates
139            where the patching needs to happen.  Collect
140            the return address and, exit back to C land,
141            handing the caller the pair (Chain_me_S, RA) */
142         mov  x1, #VG_TRC_CHAIN_ME_TO_SLOW_EP
143         mov  x2, x30 // 30 == LR
144         /* 4 = movw x9, disp_cp_chain_me_to_slowEP[15:0]
145            4 = movk x9, disp_cp_chain_me_to_slowEP[31:16], lsl 16
146            4 = movk x9, disp_cp_chain_me_to_slowEP[47:32], lsl 32
147            4 = movk x9, disp_cp_chain_me_to_slowEP[63:48], lsl 48
148            4 = blr  x9
149         */
150         sub  x2, x2, #4+4+4+4+4
151         b    postamble
153 /* ------ Chain me to fast entry point ------ */
154 .global VG_(disp_cp_chain_me_to_fastEP)
155 VG_(disp_cp_chain_me_to_fastEP):
156         /* We got called.  The return address indicates
157            where the patching needs to happen.  Collect
158            the return address and, exit back to C land,
159            handing the caller the pair (Chain_me_F, RA) */
160         mov  x1, #VG_TRC_CHAIN_ME_TO_FAST_EP
161         mov  x2, x30 // 30 == LR
162         /* 4 = movw x9, disp_cp_chain_me_to_fastEP[15:0]
163            4 = movk x9, disp_cp_chain_me_to_fastEP[31:16], lsl 16
164            4 = movk x9, disp_cp_chain_me_to_fastEP[47:32], lsl 32
165            4 = movk x9, disp_cp_chain_me_to_fastEP[63:48], lsl 48
166            4 = blr  x9
167         */
168         sub  x2, x2, #4+4+4+4+4
169         b    postamble
171 /* ------ Indirect but boring jump ------ */
172 .global VG_(disp_cp_xindir)
173 VG_(disp_cp_xindir):
174         // Where are we going?
175         ldr  x0, [x21, #OFFSET_arm64_PC]
177         // stats only
178         adrp x4,           VG_(stats__n_xIndirs_32)
179         add  x4, x4, :lo12:VG_(stats__n_xIndirs_32)
180         ldr  w5, [x4, #0]
181         add  w5, w5, #1
182         str  w5, [x4, #0]
184         // LIVE: x21 (guest state ptr), x0 (guest address to go to).
185         // We use 6 temporaries:
186         //   x6 (to point at the relevant FastCacheSet),
187         //   x1, x2, x3 (scratch, for swapping entries within a set)
188         //   x4, x5 (other scratch)
190         /* Try a fast lookup in the translation cache.  This is pretty much
191            a handcoded version of VG_(lookupInFastCache). */
193         // Compute x6 = VG_TT_FAST_HASH(guest)
194         lsr  x6, x0, #2                       // g2 = guest >> 2
195         eor  x6, x6, x6, LSR #VG_TT_FAST_BITS // (g2 >> VG_TT_FAST_BITS) ^ g2
196         mov  x4, #VG_TT_FAST_MASK             // VG_TT_FAST_MASK
197         and  x6, x6, x4                       // setNo
199         // Compute x6 = &VG_(tt_fast)[x6]
200         adrp x4,           VG_(tt_fast)
201         add  x4, x4, :lo12:VG_(tt_fast)              // &VG_(tt_fast)[0]
202         add  x6, x4, x6, LSL #VG_FAST_CACHE_SET_BITS // &VG_(tt_fast)[setNo]
204         // LIVE: x21 (guest state ptr), x0 (guest addr), x6 (cache set)
205         // try way 0
206         ldp  x4, x5, [x6, #FCS_g0]  // x4 = .guest0, x5 = .host0
207         cmp  x4, x0   // cmp against .guest0
208         bne  1f
209         // hit at way 0
210         // goto .host0
211         br   x5
212         /*NOTREACHED*/
214 1:      // try way 1
215         ldr  x4, [x6, #FCS_g1]
216         cmp  x4, x0   // cmp against .guest1
217         bne  2f
218         // hit at way 1; swap upwards
219         ldr  x1, [x6, #FCS_g0]   // x1 = old .guest0
220         ldr  x2, [x6, #FCS_h0]   // x2 = old .host0
221         ldr  x3, [x6, #FCS_h1]   // x3 = old .host1
222         str  x0, [x6, #FCS_g0]   // new .guest0 = guest
223         str  x3, [x6, #FCS_h0]   // new .host0 = old .host1
224         str  x1, [x6, #FCS_g1]   // new .guest1 = old .guest0
225         str  x2, [x6, #FCS_h1]   // new .host1 = old .host0
226         // stats only
227         adrp x4,           VG_(stats__n_xIndir_hits1_32)
228         add  x4, x4, :lo12:VG_(stats__n_xIndir_hits1_32)
229         ldr  w5, [x4, #0]
230         add  w5, w5, #1
231         str  w5, [x4, #0]
232         // goto old .host1 a.k.a. new .host0
233         br   x3
234         /*NOTREACHED*/
236 2:      // try way 2
237         ldr  x4, [x6, #FCS_g2]
238         cmp  x4, x0   // cmp against .guest2
239         bne  3f
240         // hit at way 2; swap upwards
241         ldr  x1, [x6, #FCS_g1]
242         ldr  x2, [x6, #FCS_h1]
243         ldr  x3, [x6, #FCS_h2]
244         str  x0, [x6, #FCS_g1]
245         str  x3, [x6, #FCS_h1]
246         str  x1, [x6, #FCS_g2]
247         str  x2, [x6, #FCS_h2]
248         // stats only
249         adrp x4,           VG_(stats__n_xIndir_hits2_32)
250         add  x4, x4, :lo12:VG_(stats__n_xIndir_hits2_32)
251         ldr  w5, [x4, #0]
252         add  w5, w5, #1
253         str  w5, [x4, #0]
254         // goto old .host2 a.k.a. new .host1
255         br   x3
256         /*NOTREACHED*/
258 3:      // try way 3
259         ldr  x4, [x6, #FCS_g3]
260         cmp  x4, x0   // cmp against .guest3
261         bne  4f
262         // hit at way 3; swap upwards
263         ldr  x1, [x6, #FCS_g2]
264         ldr  x2, [x6, #FCS_h2]
265         ldr  x3, [x6, #FCS_h3]
266         str  x0, [x6, #FCS_g2]
267         str  x3, [x6, #FCS_h2]
268         str  x1, [x6, #FCS_g3]
269         str  x2, [x6, #FCS_h3]
270         // stats only
271         adrp x4,           VG_(stats__n_xIndir_hits3_32)
272         add  x4, x4, :lo12:VG_(stats__n_xIndir_hits3_32)
273         ldr  w5, [x4, #0]
274         add  w5, w5, #1
275         str  w5, [x4, #0]
276         // goto old .host3 a.k.a. new .host2
277         br   x3
278         /*NOTREACHED*/
280 4:      // fast lookup failed
281         adrp x4,           VG_(stats__n_xIndir_misses_32)
282         add  x4, x4, :lo12:VG_(stats__n_xIndir_misses_32)
283         ldr  w5, [x4, #0]
284         add  w5, w5, #1
285         str  w5, [x4, #0]
287         mov  x1, #VG_TRC_INNER_FASTMISS
288         mov  x2, #0
289         b    postamble
291 /* ------ Assisted jump ------ */
292 .global VG_(disp_cp_xassisted)
293 VG_(disp_cp_xassisted):
294         /* x21 contains the TRC */
295         mov  x1, x21
296         mov  x2, #0
297         b    postamble
299 /* ------ Event check failed ------ */
300 .global VG_(disp_cp_evcheck_fail)
301 VG_(disp_cp_evcheck_fail):
302         mov  x1, #VG_TRC_INNER_COUNTERZERO
303         mov  x2, #0
304         b    postamble
307 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
309 #endif // defined(VGP_arm64_freebsd)
311 /* Let the linker know we don't need an executable stack */
312 MARK_STACK_NO_EXEC
314 /*--------------------------------------------------------------------*/
315 /*--- end                                 dispatch-arm64-freebsd.S ---*/
316 /*--------------------------------------------------------------------*/