2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address. ---*/
4 /*--- dispatch-mips-linux.S ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
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 /*------------------------------------------------------------*/
40 /*--- The dispatch loop. VG_(disp_run_translations) is ---*/
41 /*--- used to run all translations, ---*/
42 /*--- including no-redir ones. ---*/
44 /*------------------------------------------------------------*/
46 /*----------------------------------------------------*/
47 /*--- Entry and preamble (set everything up) ---*/
48 /*----------------------------------------------------*/
51 void VG_(disp_run_translations)( UWord* two_words,
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) */
79 /* ... and gp, fp/s8 */
83 /* Save a0 ($4) on stack. In postamble it will be restored such that the
84 return values can be written */
87 /* Load address of guest state into guest state register ($23) */
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
98 /*----------------------------------------------------*/
99 /*--- Postamble and exit. ---*/
100 /*----------------------------------------------------*/
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 */
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... */
119 /* ... and s0 - s7 */
129 /* ... and gp, fp/s8 */
133 addiu $29, 64 /* stack_size */
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
150 /* 8 = mkLoadImm_EXACTLY2or5
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
165 /* 8 = mkLoadImm_EXACTLY2or5
171 /* ------ Indirect but boring jump ------ */
172 .global VG_(disp_cp_xindir)
174 /* Where are we going? */
175 lw $10, OFFSET_mips32_PC($23)
178 lw $15, VG_(stats__n_xIndirs_32)
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]
200 sll $16, $16, VG_FAST_CACHE_SET_BITS
203 // LIVE: r23 (guest state ptr), r10 (guest addr), r16 (cache set)
205 lw $14, FCS_g0($16) // .guest0
206 lw $15, FCS_h0($16) // .host0
207 bne $14, $10, 1f // cmp against .guest0
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
226 lw $15, VG_(stats__n_xIndir_hits1_32)
228 sw $15, VG_(stats__n_xIndir_hits1_32)
229 // goto old .host1 a.k.a. new .host0
236 bne $14, $10, 3f // cmp against .guest2
237 // hit at way 2; swap upwards
246 lw $15, VG_(stats__n_xIndir_hits2_32)
248 sw $15, VG_(stats__n_xIndir_hits2_32)
249 // goto old .host2 a.k.a. new .host1
256 bne $14, $10, 4f // cmp against .guest3
257 // hit at way 3; swap upwards
266 lw $15, VG_(stats__n_xIndir_hits3_32)
268 sw $15, VG_(stats__n_xIndir_hits3_32)
269 // goto old .host3 a.k.a. new .host2
274 4: // fast lookup failed:
276 lw $15, VG_(stats__n_xIndir_misses_32)
278 sw $15, VG_(stats__n_xIndir_misses_32)
280 li $2, VG_TRC_INNER_FASTMISS
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
295 /* ------ Event check failed ------ */
296 .global VG_(disp_cp_evcheck_fail)
297 VG_(disp_cp_evcheck_fail):
298 li $2, VG_TRC_INNER_COUNTERZERO
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 */
309 /*--------------------------------------------------------------------*/
311 /*--------------------------------------------------------------------*/