sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 1 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 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 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame^] | 11 | Copyright (C) 2008-2017 Evan Geller |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 12 | gaze@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 | |
florian | 3f1d613 | 2015-09-30 20:30:48 +0000 | [diff] [blame] | 32 | #include "pub_core_basics_asm.h" |
| 33 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 34 | #if defined(VGP_arm_linux) |
sewardj | 223125d | 2010-08-22 12:03:45 +0000 | [diff] [blame] | 35 | .fpu vfp |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 36 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 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 | /*--- ---*/ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 44 | /*--- The dispatch loop. VG_(disp_run_translations) is ---*/ |
| 45 | /*--- used to run all translations, ---*/ |
| 46 | /*--- including no-redir ones. ---*/ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 47 | /*--- ---*/ |
| 48 | /*------------------------------------------------------------*/ |
| 49 | |
| 50 | /*----------------------------------------------------*/ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 51 | /*--- Entry and preamble (set everything up) ---*/ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 52 | /*----------------------------------------------------*/ |
| 53 | |
| 54 | /* signature: |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 55 | void VG_(disp_run_translations)( UWord* two_words, |
| 56 | void* guest_state, |
| 57 | Addr host_addr ); |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 58 | */ |
| 59 | .text |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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} |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 69 | |
| 70 | /* set FPSCR to vex-required default value */ |
| 71 | mov r4, #0 |
| 72 | fmxr fpscr, r4 |
| 73 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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 */ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 84 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 85 | /*----------------------------------------------------*/ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 86 | /*--- Postamble and exit. ---*/ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 87 | /*----------------------------------------------------*/ |
| 88 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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.) */ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 95 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 96 | /* We're leaving. Check that nobody messed with |
| 97 | FPSCR in ways we don't expect. */ |
| 98 | fmrx r4, fpscr |
sewardj | 223125d | 2010-08-22 12:03:45 +0000 | [diff] [blame] | 99 | bic r4, #0xF8000000 /* mask out NZCV and QC */ |
| 100 | bic r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 101 | cmp r4, #0 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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 */ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 107 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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 |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 115 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 116 | /*----------------------------------------------------*/ |
| 117 | /*--- Continuation points ---*/ |
| 118 | /*----------------------------------------------------*/ |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 119 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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 | |
sewardj | 5f55436 | 2012-04-21 23:12:07 +0000 | [diff] [blame] | 156 | /* stats only */ |
| 157 | movw r1, #:lower16:vgPlain_stats__n_xindirs_32 |
| 158 | movt r1, #:upper16:vgPlain_stats__n_xindirs_32 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 159 | ldr r2, [r1, #0] |
sewardj | 5f55436 | 2012-04-21 23:12:07 +0000 | [diff] [blame] | 160 | add r2, r2, #1 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 161 | str r2, [r1, #0] |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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 */ |
sewardj | 5f55436 | 2012-04-21 23:12:07 +0000 | [diff] [blame] | 182 | movw r1, #:lower16:vgPlain_stats__n_xindir_misses_32 |
| 183 | movt r1, #:upper16:vgPlain_stats__n_xindir_misses_32 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 184 | ldr r2, [r1, #0] |
sewardj | 5f55436 | 2012-04-21 23:12:07 +0000 | [diff] [blame] | 185 | add r2, r2, #1 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 186 | str r2, [r1, #0] |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 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 |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 206 | |
| 207 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 208 | .size VG_(disp_run_translations), .-VG_(disp_run_translations) |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 209 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 210 | #endif // defined(VGP_arm_linux) |
| 211 | |
florian | 3f1d613 | 2015-09-30 20:30:48 +0000 | [diff] [blame] | 212 | /* Let the linker know we don't need an executable stack */ |
| 213 | MARK_STACK_NO_EXEC |
| 214 | |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 215 | /*--------------------------------------------------------------------*/ |
| 216 | /*--- end dispatch-arm-linux.S ---*/ |
| 217 | /*--------------------------------------------------------------------*/ |