Add 469782 to NEWS
[valgrind.git] / coregrind / m_dispatch / dispatch-mips32-linux.S
blob2b077c3c7918405b42daed47463726242477adb8
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                        dispatch-mips-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_mips32_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 8 aligned (at least) */
64     addiu $29, -64
66     /* Save ra */
67     sw  $31, 16($29)
69     /* ... and s0 - s7 */
70     sw $16, 20($29)
71     sw $17, 24($29)
72     sw $18, 28($29)
73     sw $19, 32($29)
74     sw $20, 36($29)
75     sw $21, 40($29)
76     sw $22, 44($29)
77     sw $23, 48($29)
79     /* ... and gp, fp/s8 */
80     sw $28, 52($29)
81     sw $30, 56($29)
83     /* Save a0 ($4) on stack. In postamble it will be restored such that the
84        return values can be written */
85     sw $4, 60($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*/
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     lw $4, 60($29)
111     sw  $2, 0($4)         /* Store $2 to two_words[0] */
112     sw  $3, 4($4)         /* Store $3 to two_words[1] */
114     /* Restore callee-saved registers... */
116     /* Restore ra */
117     lw $31, 16($29)
119     /* ... and s0 - s7 */
120     lw $16, 20($29)
121     lw $17, 24($29)
122     lw $18, 28($29)
123     lw $19, 32($29)
124     lw $20, 36($29)
125     lw $21, 40($29)
126     lw $22, 44($29)
127     lw $23, 48($29)
129     /* ... and gp, fp/s8 */
130     lw $28, 52($29)
131     lw $30, 56($29)
133     addiu $29, 64   /* stack_size */
134     jr $31
135     nop
137 /*----------------------------------------------------*/
138 /*--- Continuation points                          ---*/
139 /*----------------------------------------------------*/
141 /* ------ Chain me to slow entry point ------ */
142 .global VG_(disp_cp_chain_me_to_slowEP)
143 VG_(disp_cp_chain_me_to_slowEP):
144         /* We got called.  The return address indicates
145            where the patching needs to happen.  Collect
146            the return address and, exit back to C land,
147            handing the caller the pair (Chain_me_S, RA) */
148         li $2, VG_TRC_CHAIN_ME_TO_SLOW_EP
149         move $3, $31
150         /* 8 = mkLoadImm_EXACTLY2or5
151            4 = jalr $9
152            4 = nop */
153         addiu  $3, $3, -16
154         b    postamble
156 /* ------ Chain me to slow entry point ------ */
157 .global VG_(disp_cp_chain_me_to_fastEP)
158 VG_(disp_cp_chain_me_to_fastEP):
159         /* We got called.  The return address indicates
160            where the patching needs to happen.  Collect
161            the return address and, exit back to C land,
162            handing the caller the pair (Chain_me_S, RA) */
163         li $2, VG_TRC_CHAIN_ME_TO_FAST_EP
164         move $3, $31
165         /* 8 = mkLoadImm_EXACTLY2or5
166            4 = jalr $9
167            4 = nop */
168         addiu  $3, $3, -16
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         lw    $10, OFFSET_mips32_PC($23)
177         /* stats only */
178         lw    $15, VG_(stats__n_xIndirs_32)
179         addiu $15, $15, 1
180         sw    $15, VG_(stats__n_xIndirs_32)
182         // LIVE: r23 (guest state ptr), r10 (guest address to go to).
183         // We use 6 temporaries:
184         //   r16 (to point at the relevant FastCacheSet),
185         //   r11, r12, r13 (scratch, for swapping entries within a set)
186         //   r14, r15 (other scratch)
188         /* Try a fast lookup in the translation cache.  This is pretty much
189            a handcoded version of VG_(lookupInFastCache). */
191         // Compute r16 = VG_TT_FAST_HASH(guest)
192         srl   $16, $10, 2                      // g2 = guest >> 2
193         srl   $15, $10, (VG_TT_FAST_BITS + 2)  // (g2 >> VG_TT_FAST_BITS)
194         xor   $16, $16, $15                    // (g2 >> VG_TT_FAST_BITS) ^ g2
195         li    $15, VG_TT_FAST_MASK
196         and   $16, $16, $15                    // setNo
198         // Compute r16 = &VG_(tt_fast)[r16]
199         la    $15, VG_(tt_fast)
200         sll   $16, $16, VG_FAST_CACHE_SET_BITS
201         addu  $16, $16, $15
203         // LIVE: r23 (guest state ptr), r10 (guest addr), r16 (cache set)
204         // try way 0
205         lw    $14, FCS_g0($16)   // .guest0
206         lw    $15, FCS_h0($16)   // .host0
207         bne   $14, $10, 1f  // cmp against .guest0
208         // hit at way 0
209         // goto .host0
210         jr    $15
211         /*NOTREACHED*/
212         .long 0x0
214 1:      // try way 1
215         lw    $14, FCS_g1($16)
216         bne   $14, $10, 2f  // cmp against .guest1
217         // hit at way 1; swap upwards
218         lw    $11, FCS_g0($16)   // $11 = old .guest0
219         lw    $12, FCS_h0($16)   // $12 = old .host0
220         lw    $13, FCS_h1($16)   // $13 = old .host1
221         sw    $10, FCS_g0($16)   // new .guest0 = guest
222         sw    $13, FCS_h0($16)   // new .host0 = old .host1
223         sw    $11, FCS_g1($16)   // new .guest1 = old .guest0
224         sw    $12, FCS_h1($16)   // new .host1 = old .host0
225         // stats only
226         lw    $15, VG_(stats__n_xIndir_hits1_32)
227         addiu $15, $15, 1
228         sw    $15, VG_(stats__n_xIndir_hits1_32)
229         // goto old .host1 a.k.a. new .host0
230         jr    $13
231         /*NOTREACHED*/
232         .long 0x0
234 2:      // try way 2
235         lw    $14, FCS_g2($16)
236         bne   $14, $10, 3f   // cmp against .guest2
237         // hit at way 2; swap upwards
238         lw    $11, FCS_g1($16)
239         lw    $12, FCS_h1($16)
240         lw    $13, FCS_h2($16)
241         sw    $10, FCS_g1($16)
242         sw    $13, FCS_h1($16)
243         sw    $11, FCS_g2($16)
244         sw    $12, FCS_h2($16)
245         // stats only
246         lw    $15, VG_(stats__n_xIndir_hits2_32)
247         addiu $15, $15, 1
248         sw    $15, VG_(stats__n_xIndir_hits2_32)
249         // goto old .host2 a.k.a. new .host1
250         jr    $13
251         /*NOTREACHED*/
252         .long 0x0
254 3:      // try way 3
255         lw    $14, FCS_g3($16)
256         bne   $14, $10, 4f   // cmp against .guest3
257         // hit at way 3; swap upwards
258         lw    $11, FCS_g2($16)
259         lw    $12, FCS_h2($16)
260         lw    $13, FCS_h3($16)
261         sw    $10, FCS_g2($16)
262         sw    $13, FCS_h2($16)
263         sw    $11, FCS_g3($16)
264         sw    $12, FCS_h3($16)
265         // stats only
266         lw    $15, VG_(stats__n_xIndir_hits3_32)
267         addiu $15, $15, 1
268         sw    $15, VG_(stats__n_xIndir_hits3_32)
269         // goto old .host3 a.k.a. new .host2
270         jr    $13
271         /*NOTREACHED*/
272         .long 0x0
274 4:      // fast lookup failed:
275         /* stats only */
276         lw    $15, VG_(stats__n_xIndir_misses_32)
277         addiu $15, $15, 1
278         sw    $15, VG_(stats__n_xIndir_misses_32)
280         li    $2, VG_TRC_INNER_FASTMISS
281         li    $3, 0
282         b     postamble
283         /*NOTREACHED*/
284         .long 0x0
286 /* ------ Assisted jump ------ */
287         .global VG_(disp_cp_xassisted)
288 VG_(disp_cp_xassisted):
289         /* guest-state-pointer contains the TRC. Put the value into the
290            return register */
291         move    $2, $23
292         move    $3, $0
293         b       postamble
295 /* ------ Event check failed ------ */
296         .global VG_(disp_cp_evcheck_fail)
297 VG_(disp_cp_evcheck_fail):
298         li      $2, VG_TRC_INNER_COUNTERZERO
299         move    $3, $0
300         b       postamble
302 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
304 #endif // defined(VGP_mips32_linux)
306 /* Let the linker know we don't need an executable stack */
307 MARK_STACK_NO_EXEC
309 /*--------------------------------------------------------------------*/
310 /*--- end                                                          ---*/
311 /*--------------------------------------------------------------------*/