2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address. ---*/
4 /*--- dispatch-mips64-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_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 /*------------------------------------------------------------*/
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 16 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 #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] */
118 #error unknown mips64 abi
121 /* Restore callee-saved registers... */
126 /* ... and s0 - s7 */
136 /* ... and gp, fp/s8 */
140 daddiu $29, 176 /* stack_size */
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
157 /* 8 = mkLoadImm_EXACTLY2or6
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
172 /* 8 = mkLoadImm_EXACTLY2or6
178 /* ------ Indirect but boring jump ------ */
179 .global VG_(disp_cp_xindir)
181 /* Where are we going? */
182 ld $10, OFFSET_mips64_PC($23)
185 lw $15, VG_(stats__n_xIndirs_32)
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
210 // LIVE: r23 (guest state ptr), r10 (guest addr), r16 (cache set)
212 ld $14, FCS_g0($16) // .guest0
213 ld $15, FCS_h0($16) // .host0
214 bne $14, $10, 1f // cmp against .guest0
222 #if defined(VGABI_64)
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)
245 lw $15, VG_(stats__n_xIndir_hits1_32)
247 sw $15, VG_(stats__n_xIndir_hits1_32)
248 // goto old .host1 a.k.a. new .host0
254 #if defined(VGABI_64)
256 bne $14, $10, 3f // cmp against .guest2
257 // hit at way 2; swap upwards
265 #elif defined(VGABI_N32)
277 lw $15, VG_(stats__n_xIndir_hits2_32)
279 sw $15, VG_(stats__n_xIndir_hits2_32)
280 // goto old .host2 a.k.a. new .host1
286 #if defined(VGABI_64)
288 bne $14, $10, 4f // cmp against .guest3
289 // hit at way 3; swap upwards
297 #elif defined(VGABI_N32)
309 lw $15, VG_(stats__n_xIndir_hits3_32)
311 sw $15, VG_(stats__n_xIndir_hits3_32)
312 // goto old .host3 a.k.a. new .host2
317 4: // fast lookup failed:
319 lw $15, VG_(stats__n_xIndir_misses_32)
321 sw $15, VG_(stats__n_xIndir_misses_32)
323 li $2, VG_TRC_INNER_FASTMISS
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
338 /* ------ Event check failed ------ */
339 .global VG_(disp_cp_evcheck_fail)
340 VG_(disp_cp_evcheck_fail):
341 li $2, VG_TRC_INNER_COUNTERZERO
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 */
352 /*--------------------------------------------------------------------*/
354 /*--------------------------------------------------------------------*/