Add 469782 to NEWS
[valgrind.git] / coregrind / m_dispatch / dispatch-mips64-linux.S
blobf5b79ba1e81ffedb80703eb303b4b8aeb3fe6e8a
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                      dispatch-mips64-linux.S ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
11   Copyright (C) 2000-2017 RT-RK
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.
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.
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, see <http://www.gnu.org/licenses/>.
26   The GNU General Public License is contained in the file COPYING.
29 #include "pub_core_basics_asm.h"
31 #if defined(VGP_mips64_linux)
33 #include "pub_core_dispatch_asm.h"
34 #include "pub_core_transtab_asm.h"
35 #include "libvex_guest_offsets.h"       /* for OFFSET_mips_PC */
38 /*------------------------------------------------------------*/
39 /*---                                                      ---*/
40 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
41 /*--- used to run all translations,                        ---*/
42 /*--- including no-redir ones.                             ---*/
43 /*---                                                      ---*/
44 /*------------------------------------------------------------*/
46 /*----------------------------------------------------*/
47 /*--- Entry and preamble (set everything up)       ---*/
48 /*----------------------------------------------------*/
50 /* signature:
51 void VG_(disp_run_translations)( UWord* two_words,
52                                  void*  guest_state, 
53                                  Addr   host_addr );
56 .text
57 .globl VG_(disp_run_translations)
58 VG_(disp_run_translations):
59     /* a0 ($4) holds two_words   */
60     /* a1 ($5) holds guest_state */
61     /* a2 ($6) holds host_addr   */
63     /* New stack frame.  Stack must remain 16 aligned (at least) */
64     daddiu $29, -176
66     /* Save ra */
67     sd  $31, 72($29)
69     /* ... and s0 - s7 */
70     sd $16, 80($29)
71     sd $17, 88($29)
72     sd $18, 96($29)
73     sd $19, 104($29)
74     sd $20, 112($29)
75     sd $21, 120($29)
76     sd $22, 128($29)
77     sd $23, 136($29)
79     /* ... and gp, fp/s8 */
80     sd $28, 144($29)
81     sd $30, 152($29)
83     /* Save a0 ($4) on stack. In postamble it will be restored such that the
84        return values can be written */
85     sd $4, 160($29)
87     /* Load address of guest state into guest state register ($23) */
88     move $23, $5
90     /* and jump into the code cache.  Chained translations in
91            the code cache run, until for whatever reason, they can't
92            continue.  When that happens, the translation in question
93            will jump (or call) to one of the continuation points
94            VG_(cp_...) below. */
95     jr $6
96     /*NOTREACHED*/
97     
98 /*----------------------------------------------------*/
99 /*--- Postamble and exit.                          ---*/
100 /*----------------------------------------------------*/
102 postamble:
103         /* At this point, $2 and $3 contain two
104            words to be returned to the caller.  $2
105            holds a TRC value, and $3 optionally may
106            hold another word (for CHAIN_ME exits, the
107            address of the place to patch.) */
109     /* Restore $4 from stack; holds address of two_words */
110     ld $4, 160($29)
111     #if defined(VGABI_64)
112      sd  $2, 0($4)         /* Store $2 to two_words[0] */
113      sd  $3, 8($4)         /* Store $3 to two_words[1] */
114     #elif defined(VGABI_N32)
115      sw  $2, 0($4)         /* Store $2 to two_words[0] */
116      sw  $3, 4($4)         /* Store $3 to two_words[1] */
117     #else
118     #error unknown mips64 abi
119     #endif
121     /* Restore callee-saved registers... */
123     /* Restore ra */
124     ld $31, 72($29)
126     /* ... and s0 - s7 */
127     ld $16, 80($29)
128     ld $17, 88($29)
129     ld $18, 96($29)
130     ld $19, 104($29)
131     ld $20, 112($29)
132     ld $21, 120($29)
133     ld $22, 128($29)
134     ld $23, 136($29)
136     /* ... and gp, fp/s8 */
137     ld $28, 144($29)
138     ld $30, 152($29)
140     daddiu $29, 176   /* stack_size */
141     jr $31
142     nop
144 /*----------------------------------------------------*/
145 /*--- Continuation points                          ---*/
146 /*----------------------------------------------------*/
148 /* ------ Chain me to slow entry point ------ */
149 .global VG_(disp_cp_chain_me_to_slowEP)
150 VG_(disp_cp_chain_me_to_slowEP):
151         /* We got called.  The return address indicates
152            where the patching needs to happen.  Collect
153            the return address and, exit back to C land,
154            handing the caller the pair (Chain_me_S, RA) */
155         li $2, VG_TRC_CHAIN_ME_TO_SLOW_EP
156         move $3, $31
157         /* 8 = mkLoadImm_EXACTLY2or6
158            4 = jalr $9
159            4 = nop */
160         daddiu  $3, $3, -32
161         b    postamble
163 /* ------ Chain me to slow entry point ------ */
164 .global VG_(disp_cp_chain_me_to_fastEP)
165 VG_(disp_cp_chain_me_to_fastEP):
166         /* We got called.  The return address indicates
167            where the patching needs to happen.  Collect
168            the return address and, exit back to C land,
169            handing the caller the pair (Chain_me_S, RA) */
170         li $2, VG_TRC_CHAIN_ME_TO_FAST_EP
171         move $3, $31
172         /* 8 = mkLoadImm_EXACTLY2or6
173            4 = jalr $9
174            4 = nop */
175         daddiu  $3, $3, -32
176         b    postamble
178 /* ------ Indirect but boring jump ------ */
179 .global VG_(disp_cp_xindir)
180 VG_(disp_cp_xindir):
181         /* Where are we going? */
182         ld    $10, OFFSET_mips64_PC($23)
184         /* stats only */
185         lw    $15, VG_(stats__n_xIndirs_32)
186         addiu $15, $15, 1
187         sw    $15, VG_(stats__n_xIndirs_32)
189         // LIVE: r23 (guest state ptr), r10 (guest address to go to).
190         // We use 6 temporaries:
191         //   r16 (to point at the relevant FastCacheSet),
192         //   r11, r12, r13 (scratch, for swapping entries within a set)
193         //   r14, r15 (other scratch)
195         /* Try a fast lookup in the translation cache.  This is pretty much
196            a handcoded version of VG_(lookupInFastCache). */
198         // Compute r16 = VG_TT_FAST_HASH(guest)
199         dsrl  $16, $10, 2                      // g2 = guest >> 2
200         dsrl  $15, $10, (VG_TT_FAST_BITS + 2)  // (g2 >> VG_TT_FAST_BITS)
201         xor   $16, $16, $15                    // (g2 >> VG_TT_FAST_BITS) ^ g2
202         li    $15, VG_TT_FAST_MASK
203         and   $16, $16, $15                    // setNo
205         // Compute r16 = &VG_(tt_fast)[r16]
206         dla   $15, VG_(tt_fast)
207         dsll  $16, $16, VG_FAST_CACHE_SET_BITS
208         daddu $16, $16, $15
210         // LIVE: r23 (guest state ptr), r10 (guest addr), r16 (cache set)
211         // try way 0
212         ld    $14, FCS_g0($16)   // .guest0
213         ld    $15, FCS_h0($16)   // .host0
214         bne   $14, $10, 1f  // cmp against .guest0
215         // hit at way 0
216         // goto .host0
217         jr    $15
218         /*NOTREACHED*/
219         .long 0x0
221 1:      // try way 1
222         #if defined(VGABI_64)
223         ld    $14, FCS_g1($16)
224         bne   $14, $10, 2f  // cmp against .guest1
225         // hit at way 1; swap upwards
226         ld    $11, FCS_g0($16)   // $11 = old .guest0
227         ld    $12, FCS_h0($16)   // $12 = old .host0
228         ld    $13, FCS_h1($16)   // $13 = old .host1
229         sd    $10, FCS_g0($16)   // new .guest0 = guest
230         sd    $13, FCS_h0($16)   // new .host0 = old .host1
231         sd    $11, FCS_g1($16)   // new .guest1 = old .guest0
232         sd    $12, FCS_h1($16)   // new .host1 = old .host0
233         #elif defined(VGABI_N32)
234         lw    $14, FCS_g1($16)
235         bne   $14, $10, 2f
236         lw    $11, FCS_g0($16)
237         lw    $12, FCS_h0($16)
238         lw    $13, FCS_h1($16)
239         sw    $10, FCS_g0($16)
240         sw    $13, FCS_h0($16)
241         sw    $11, FCS_g1($16)
242         sw    $12, FCS_h1($16)
243         #endif
244         // stats only
245         lw    $15, VG_(stats__n_xIndir_hits1_32)
246         addiu $15, $15, 1
247         sw    $15, VG_(stats__n_xIndir_hits1_32)
248         // goto old .host1 a.k.a. new .host0
249         jr    $13
250         /*NOTREACHED*/
251         .long 0x0
253 2:      // try way 2
254         #if defined(VGABI_64)
255         ld    $14, FCS_g2($16)
256         bne   $14, $10, 3f   // cmp against .guest2
257         // hit at way 2; swap upwards
258         ld    $11, FCS_g1($16)
259         ld    $12, FCS_h1($16)
260         ld    $13, FCS_h2($16)
261         sd    $10, FCS_g1($16)
262         sd    $13, FCS_h1($16)
263         sd    $11, FCS_g2($16)
264         sd    $12, FCS_h2($16)
265         #elif defined(VGABI_N32)
266         lw    $14, FCS_g2($16)
267         bne   $14, $10, 3f
268         lw    $11, FCS_g1($16)
269         lw    $12, FCS_h1($16)
270         lw    $13, FCS_h2($16)
271         sw    $10, FCS_g1($16)
272         sw    $13, FCS_h1($16)
273         sw    $11, FCS_g2($16)
274         sw    $12, FCS_h2($16)
275         #endif
276         // stats only
277         lw    $15, VG_(stats__n_xIndir_hits2_32)
278         addiu $15, $15, 1
279         sw    $15, VG_(stats__n_xIndir_hits2_32)
280         // goto old .host2 a.k.a. new .host1
281         jr    $13
282         /*NOTREACHED*/
283         .long 0x0
285 3:      // try way 3
286         #if defined(VGABI_64)
287         ld    $14, FCS_g3($16)
288         bne   $14, $10, 4f   // cmp against .guest3
289         // hit at way 3; swap upwards
290         ld    $11, FCS_g2($16)
291         ld    $12, FCS_h2($16)
292         ld    $13, FCS_h3($16)
293         sd    $10, FCS_g2($16)
294         sd    $13, FCS_h2($16)
295         sd    $11, FCS_g3($16)
296         sd    $12, FCS_h3($16)
297         #elif defined(VGABI_N32)
298         lw    $14, FCS_g3($16)
299         bne   $14, $10, 4f
300         lw    $11, FCS_g2($16)
301         lw    $12, FCS_h2($16)
302         lw    $13, FCS_h3($16)
303         sw    $10, FCS_g2($16)
304         sw    $13, FCS_h2($16)
305         sw    $11, FCS_g3($16)
306         sw    $12, FCS_h3($16)
307         #endif
308         // stats only
309         lw    $15, VG_(stats__n_xIndir_hits3_32)
310         addiu $15, $15, 1
311         sw    $15, VG_(stats__n_xIndir_hits3_32)
312         // goto old .host3 a.k.a. new .host2
313         jr    $13
314         /*NOTREACHED*/
315         .long 0x0
317 4:      // fast lookup failed:
318         /* stats only */
319         lw    $15, VG_(stats__n_xIndir_misses_32)
320         addiu $15, $15, 1
321         sw    $15, VG_(stats__n_xIndir_misses_32)
323         li    $2, VG_TRC_INNER_FASTMISS
324         li    $3, 0
325         b     postamble
326         /*NOTREACHED*/
327         .long 0x0
329 /* ------ Assisted jump ------ */
330         .global VG_(disp_cp_xassisted)
331 VG_(disp_cp_xassisted):
332         /* guest-state-pointer contains the TRC. Put the value into the
333            return register */
334         move    $2, $23
335         move    $3, $0
336         b       postamble
338 /* ------ Event check failed ------ */
339         .global VG_(disp_cp_evcheck_fail)
340 VG_(disp_cp_evcheck_fail):
341         li      $2, VG_TRC_INNER_COUNTERZERO
342         move    $3, $0
343         b       postamble
345 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
347 #endif // defined(VGP_mips64_linux)
349 /* Let the linker know we don't need an executable stack */
350 MARK_STACK_NO_EXEC
352 /*--------------------------------------------------------------------*/
353 /*--- end                                                          ---*/
354 /*--------------------------------------------------------------------*/