1 2 /*--------------------------------------------------------------------*/ 3 /*--- The core dispatch loop, for jumping to a code address. ---*/ 4 /*--- dispatch-arm-linux.S ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2008-2015 Evan Geller 12 gaze (at) bea.ms 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 #include "pub_core_basics_asm.h" 33 34 #if defined(VGP_arm_linux) 35 .fpu vfp 36 37 #include "pub_core_dispatch_asm.h" 38 #include "pub_core_transtab_asm.h" 39 #include "libvex_guest_offsets.h" /* for OFFSET_arm_R* */ 40 41 42 /*------------------------------------------------------------*/ 43 /*--- ---*/ 44 /*--- The dispatch loop. VG_(disp_run_translations) is ---*/ 45 /*--- used to run all translations, ---*/ 46 /*--- including no-redir ones. ---*/ 47 /*--- ---*/ 48 /*------------------------------------------------------------*/ 49 50 /*----------------------------------------------------*/ 51 /*--- Entry and preamble (set everything up) ---*/ 52 /*----------------------------------------------------*/ 53 54 /* signature: 55 void VG_(disp_run_translations)( UWord* two_words, 56 void* guest_state, 57 Addr host_addr ); 58 */ 59 .text 60 .global VG_(disp_run_translations) 61 VG_(disp_run_translations): 62 /* r0 holds two_words 63 r1 holds guest_state 64 r2 holds host_addr 65 */ 66 /* The number of regs in this list needs to be even, in 67 order to keep the stack 8-aligned. */ 68 push {r0, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr} 69 70 /* set FPSCR to vex-required default value */ 71 mov r4, #0 72 fmxr fpscr, r4 73 74 /* Set up the guest state pointer */ 75 mov r8, r1 76 77 /* and jump into the code cache. Chained translations in 78 the code cache run, until for whatever reason, they can't 79 continue. When that happens, the translation in question 80 will jump (or call) to one of the continuation points 81 VG_(cp_...) below. */ 82 bx r2 83 /* NOTREACHED */ 84 85 /*----------------------------------------------------*/ 86 /*--- Postamble and exit. ---*/ 87 /*----------------------------------------------------*/ 88 89 postamble: 90 /* At this point, r1 and r2 contain two 91 words to be returned to the caller. r1 92 holds a TRC value, and r2 optionally may 93 hold another word (for CHAIN_ME exits, the 94 address of the place to patch.) */ 95 96 /* We're leaving. Check that nobody messed with 97 FPSCR in ways we don't expect. */ 98 fmrx r4, fpscr 99 bic r4, #0xF8000000 /* mask out NZCV and QC */ 100 bic r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */ 101 cmp r4, #0 102 beq remove_frame /* we're OK */ 103 /* otherwise we have an invariant violation */ 104 movw r1, #VG_TRC_INVARIANT_FAILED 105 movw r2, #0 106 /* fall through */ 107 108 remove_frame: 109 /* Restore int regs, including importantly r0 (two_words) */ 110 pop {r0, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr} 111 /* Stash return values */ 112 str r1, [r0, #0] 113 str r2, [r0, #4] 114 bx lr 115 116 /*----------------------------------------------------*/ 117 /*--- Continuation points ---*/ 118 /*----------------------------------------------------*/ 119 120 /* ------ Chain me to slow entry point ------ */ 121 .global VG_(disp_cp_chain_me_to_slowEP) 122 VG_(disp_cp_chain_me_to_slowEP): 123 /* We got called. The return address indicates 124 where the patching needs to happen. Collect 125 the return address and, exit back to C land, 126 handing the caller the pair (Chain_me_S, RA) */ 127 mov r1, #VG_TRC_CHAIN_ME_TO_SLOW_EP 128 mov r2, lr 129 /* 4 = movw r12, lo16(disp_cp_chain_me_to_slowEP) 130 4 = movt r12, hi16(disp_cp_chain_me_to_slowEP) 131 4 = blx r12 */ 132 sub r2, r2, #4+4+4 133 b postamble 134 135 /* ------ Chain me to fast entry point ------ */ 136 .global VG_(disp_cp_chain_me_to_fastEP) 137 VG_(disp_cp_chain_me_to_fastEP): 138 /* We got called. The return address indicates 139 where the patching needs to happen. Collect 140 the return address and, exit back to C land, 141 handing the caller the pair (Chain_me_F, RA) */ 142 mov r1, #VG_TRC_CHAIN_ME_TO_FAST_EP 143 mov r2, lr 144 /* 4 = movw r12, lo16(disp_cp_chain_me_to_fastEP) 145 4 = movt r12, hi16(disp_cp_chain_me_to_fastEP) 146 4 = blx r12 */ 147 sub r2, r2, #4+4+4 148 b postamble 149 150 /* ------ Indirect but boring jump ------ */ 151 .global VG_(disp_cp_xindir) 152 VG_(disp_cp_xindir): 153 /* Where are we going? */ 154 ldr r0, [r8, #OFFSET_arm_R15T] 155 156 /* stats only */ 157 movw r1, #:lower16:vgPlain_stats__n_xindirs_32 158 movt r1, #:upper16:vgPlain_stats__n_xindirs_32 159 ldr r2, [r1, #0] 160 add r2, r2, #1 161 str r2, [r1, #0] 162 163 /* try a fast lookup in the translation cache */ 164 // r0 = next guest, r1,r2,r3,r4 scratch 165 movw r1, #VG_TT_FAST_MASK // r1 = VG_TT_FAST_MASK 166 movw r4, #:lower16:VG_(tt_fast) 167 168 and r2, r1, r0, LSR #1 // r2 = entry # 169 movt r4, #:upper16:VG_(tt_fast) // r4 = &VG_(tt_fast) 170 171 add r1, r4, r2, LSL #3 // r1 = &tt_fast[entry#] 172 173 ldrd r4, r5, [r1, #0] // r4 = .guest, r5 = .host 174 175 cmp r4, r0 176 177 // jump to host if lookup succeeded 178 bxeq r5 179 180 /* otherwise the fast lookup failed */ 181 /* RM ME -- stats only */ 182 movw r1, #:lower16:vgPlain_stats__n_xindir_misses_32 183 movt r1, #:upper16:vgPlain_stats__n_xindir_misses_32 184 ldr r2, [r1, #0] 185 add r2, r2, #1 186 str r2, [r1, #0] 187 188 mov r1, #VG_TRC_INNER_FASTMISS 189 mov r2, #0 190 b postamble 191 192 /* ------ Assisted jump ------ */ 193 .global VG_(disp_cp_xassisted) 194 VG_(disp_cp_xassisted): 195 /* r8 contains the TRC */ 196 mov r1, r8 197 mov r2, #0 198 b postamble 199 200 /* ------ Event check failed ------ */ 201 .global VG_(disp_cp_evcheck_fail) 202 VG_(disp_cp_evcheck_fail): 203 mov r1, #VG_TRC_INNER_COUNTERZERO 204 mov r2, #0 205 b postamble 206 207 208 .size VG_(disp_run_translations), .-VG_(disp_run_translations) 209 210 #endif // defined(VGP_arm_linux) 211 212 /* Let the linker know we don't need an executable stack */ 213 MARK_STACK_NO_EXEC 214 215 /*--------------------------------------------------------------------*/ 216 /*--- end dispatch-arm-linux.S ---*/ 217 /*--------------------------------------------------------------------*/ 218