1 2 /*--------------------------------------------------------------------*/ 3 /*--- The core dispatch loop, for jumping to a code address. ---*/ 4 /*--- dispatch-mips-linux.S ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2000-2012 RT-RK 12 mips-valgrind (at) rt-rk.com 13 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. 18 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. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30 */ 31 32 33 #if defined(VGP_mips32_linux) 34 35 #include "pub_core_basics_asm.h" 36 #include "pub_core_dispatch_asm.h" 37 #include "pub_core_transtab_asm.h" 38 #include "libvex_guest_offsets.h" /* for OFFSET_mips_PC */ 39 40 41 /*------------------------------------------------------------*/ 42 /*--- ---*/ 43 /*--- The dispatch loop. VG_(disp_run_translations) is ---*/ 44 /*--- used to run all translations, ---*/ 45 /*--- including no-redir ones. ---*/ 46 /*--- ---*/ 47 /*------------------------------------------------------------*/ 48 49 /*----------------------------------------------------*/ 50 /*--- Entry and preamble (set everything up) ---*/ 51 /*----------------------------------------------------*/ 52 53 /* signature: 54 void VG_(disp_run_translations)( UWord* two_words, 55 void* guest_state, 56 Addr host_addr ); 57 */ 58 59 .text 60 .globl VG_(disp_run_translations) 61 VG_(disp_run_translations): 62 /* a0 ($4) holds two_words */ 63 /* a1 ($5) holds guest_state */ 64 /* a2 ($6) holds host_addr */ 65 66 /* New stack frame. Stack must remain 8 aligned (at least) */ 67 addiu $29, -56 68 69 /* Save ra */ 70 sw $31, 0($29) 71 72 /* ... and orig guest state*/ 73 sw $5, 4($29) 74 75 /* ... and s0 - s7 */ 76 sw $16, 8($29) 77 sw $17, 12($29) 78 sw $18, 16($29) 79 sw $19, 20($29) 80 sw $20, 24($29) 81 sw $21, 28($29) 82 sw $22, 32($29) 83 sw $23, 36($29) 84 85 /* ... and gp, fp/s8 */ 86 sw $28, 40($29) 87 sw $30, 44($29) 88 89 /* Save a0 ($4) on stack. In postamble it will be restored such that the 90 return values can be written */ 91 sw $4, 48($29) 92 93 /* Load address of guest state into guest state register (r10) */ 94 move $10, $5 95 96 /* and jump into the code cache. Chained translations in 97 the code cache run, until for whatever reason, they can't 98 continue. When that happens, the translation in question 99 will jump (or call) to one of the continuation points 100 VG_(cp_...) below. */ 101 jr $6 102 /*NOTREACHED*/ 103 104 /*----------------------------------------------------*/ 105 /*--- Postamble and exit. ---*/ 106 /*----------------------------------------------------*/ 107 108 postamble: 109 /* At this point, r2 and r3 contain two 110 words to be returned to the caller. r2 111 holds a TRC value, and r3 optionally may 112 hold another word (for CHAIN_ME exits, the 113 address of the place to patch.) */ 114 115 /* Restore $4 from stack; holds address of two_words */ 116 lw $4, 48($29) 117 sw $2, 0($4) /* Store $2 to two_words[0] */ 118 sw $3, 4($4) /* Store $3 to two_words[1] */ 119 120 /* Restore callee-saved registers... */ 121 122 /* Restore ra */ 123 lw $31, 0($29) 124 125 /* ... and s0 - s7 */ 126 lw $16, 8($29) 127 lw $17, 12($29) 128 lw $18, 16($29) 129 lw $19, 20($29) 130 lw $20, 24($29) 131 lw $21, 28($29) 132 lw $22, 32($29) 133 lw $23, 36($29) 134 135 /* ... and gp, fp/s8 */ 136 lw $28, 40($29) 137 lw $30, 44($29) 138 139 140 addiu $29, 56 /* stack_size */ 141 jr $31 142 nop 143 144 /*----------------------------------------------------*/ 145 /*--- Continuation points ---*/ 146 /*----------------------------------------------------*/ 147 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_EXACTLY2or5 158 4 = jalr $9 159 4 = nop */ 160 addiu $3, $3, -16 161 b postamble 162 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_EXACTLY2or5 173 4 = jalr $9 174 4 = nop */ 175 addiu $3, $3, -16 176 b postamble 177 178 /* ------ Indirect but boring jump ------ */ 179 .global VG_(disp_cp_xindir) 180 VG_(disp_cp_xindir): 181 /* Where are we going? */ 182 lw $11, OFFSET_mips32_PC($10) 183 184 lw $13, vgPlain_stats__n_xindirs_32 185 addiu $13, $13, 0x1 186 sw $13, vgPlain_stats__n_xindirs_32 187 188 /* try a fast lookup in the translation cache */ 189 /* t1 = VG_TT_FAST_HASH(addr) * sizeof(ULong*) 190 = (t8 >> 2 & VG_TT_FAST_MASK) << 3 */ 191 192 move $14, $11 193 li $12, VG_TT_FAST_MASK 194 srl $14, $14, 2 195 and $14, $14, $12 196 sll $14, $14, 3 197 198 /* t2 = (addr of VG_(tt_fast)) + t1 */ 199 la $13, VG_(tt_fast) 200 addu $13, $13, $14 201 202 lw $12, 0($13) /* t3 = VG_(tt_fast)[hash] :: ULong* */ 203 addi $13, $13, 4 204 lw $25, 0($13) /* little-endian, so comparing 1st 32bit word */ 205 nop 206 207 check: 208 bne $12, $11, fast_lookup_failed 209 /* run the translation */ 210 jr $25 211 .long 0x0 /* persuade insn decoders not to speculate past here */ 212 213 fast_lookup_failed: 214 /* %PC is up to date */ 215 /* back out decrement of the dispatch counter */ 216 /* hold dispatch_ctr in t0 (r8) */ 217 lw $13, vgPlain_stats__n_xindirs_32 218 addiu $13, $13, 0x1 219 sw $13, vgPlain_stats__n_xindirs_32 220 li $2, VG_TRC_INNER_FASTMISS 221 li $3, 0 222 b postamble 223 224 /* ------ Assisted jump ------ */ 225 .global VG_(disp_cp_xassisted) 226 VG_(disp_cp_xassisted): 227 /* guest-state-pointer contains the TRC. Put the value into the 228 return register */ 229 move $2, $10 230 move $3, $0 231 b postamble 232 233 /* ------ Event check failed ------ */ 234 .global VG_(disp_cp_evcheck_fail) 235 VG_(disp_cp_evcheck_fail): 236 li $2, VG_TRC_INNER_COUNTERZERO 237 move $3, $0 238 b postamble 239 240 .size VG_(disp_run_translations), .-VG_(disp_run_translations) 241 242 243 /* Let the linker know we do not need an executable stack */ 244 .section .note.GNU-stack,"",@progbits 245 246 #endif // defined(VGP_mips32_linux) 247 /*--------------------------------------------------------------------*/ 248 /*--- end ---*/ 249 /*--------------------------------------------------------------------*/ 250