sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 1 | |
| 2 | /*---------------------------------------------------------------*/ |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 3 | /*--- begin libvex_guest_arm.h ---*/ |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 4 | /*---------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 9 | |
sewardj | 785952d | 2015-08-21 11:29:16 +0000 | [diff] [blame] | 10 | Copyright (C) 2004-2015 OpenWorks LLP |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 11 | info@open-works.net |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 12 | |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 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. |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 17 | |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 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. |
| 22 | |
| 23 | You should have received a copy of the GNU General Public License |
| 24 | along with this program; if not, write to the Free Software |
| 25 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
sewardj | 7bd6ffe | 2005-08-03 16:07:36 +0000 | [diff] [blame] | 26 | 02110-1301, USA. |
| 27 | |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 28 | The GNU General Public License is contained in the file COPYING. |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 29 | */ |
| 30 | |
| 31 | #ifndef __LIBVEX_PUB_GUEST_ARM_H |
| 32 | #define __LIBVEX_PUB_GUEST_ARM_H |
| 33 | |
| 34 | #include "libvex_basictypes.h" |
| 35 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 36 | |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 37 | /*---------------------------------------------------------------*/ |
| 38 | /*--- Vex's representation of the ARM CPU state. ---*/ |
| 39 | /*---------------------------------------------------------------*/ |
| 40 | |
| 41 | typedef |
| 42 | struct { |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 43 | /* 0 */ |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 44 | /* Event check fail addr and counter. */ |
| 45 | UInt host_EvC_FAILADDR; /* 0 */ |
| 46 | UInt host_EvC_COUNTER; /* 4 */ |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 47 | UInt guest_R0; |
| 48 | UInt guest_R1; |
| 49 | UInt guest_R2; |
| 50 | UInt guest_R3; |
| 51 | UInt guest_R4; |
| 52 | UInt guest_R5; |
| 53 | UInt guest_R6; |
| 54 | UInt guest_R7; |
| 55 | UInt guest_R8; |
| 56 | UInt guest_R9; |
| 57 | UInt guest_R10; |
| 58 | UInt guest_R11; |
| 59 | UInt guest_R12; |
| 60 | UInt guest_R13; /* stack pointer */ |
| 61 | UInt guest_R14; /* link register */ |
sewardj | d266447 | 2010-08-22 12:44:20 +0000 | [diff] [blame] | 62 | UInt guest_R15T; |
| 63 | /* program counter[31:1] ++ [T], encoding both the current |
| 64 | instruction address and the ARM vs Thumb state of the |
| 65 | machine. T==1 is Thumb, T==0 is ARM. Hence values of the |
| 66 | form X--(31)--X1 denote a Thumb instruction at location |
| 67 | X--(31)--X0, values of the form X--(30)--X00 denote an ARM |
| 68 | instruction at precisely that address, and values of the form |
| 69 | X--(30)--10 are invalid since they would imply an ARM |
| 70 | instruction at a non-4-aligned address. */ |
cerion | cee3031 | 2004-12-17 20:30:21 +0000 | [diff] [blame] | 71 | |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 72 | /* 4-word thunk used to calculate N(sign) Z(zero) C(carry, |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 73 | unsigned overflow) and V(signed overflow) flags. */ |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 74 | /* 72 */ |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 75 | UInt guest_CC_OP; |
| 76 | UInt guest_CC_DEP1; |
| 77 | UInt guest_CC_DEP2; |
| 78 | UInt guest_CC_NDEP; |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 79 | |
sewardj | d266447 | 2010-08-22 12:44:20 +0000 | [diff] [blame] | 80 | /* A 32-bit value which is used to compute the APSR.Q (sticky |
| 81 | saturation) flag, when necessary. If the value stored here |
| 82 | is zero, APSR.Q is currently zero. If it is any other value, |
| 83 | APSR.Q is currently one. */ |
| 84 | UInt guest_QFLAG32; |
| 85 | |
sewardj | 1f139f5 | 2010-08-29 12:33:02 +0000 | [diff] [blame] | 86 | /* 32-bit values to represent APSR.GE0 .. GE3. Same |
| 87 | zero-vs-nonzero scheme as for QFLAG32. */ |
| 88 | UInt guest_GEFLAG0; |
| 89 | UInt guest_GEFLAG1; |
| 90 | UInt guest_GEFLAG2; |
| 91 | UInt guest_GEFLAG3; |
| 92 | |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 93 | /* Various pseudo-regs mandated by Vex or Valgrind. */ |
florian | 6ef84be | 2012-08-26 03:20:07 +0000 | [diff] [blame] | 94 | /* Emulation notes */ |
| 95 | UInt guest_EMNOTE; |
sewardj | 893aada | 2004-11-29 19:57:54 +0000 | [diff] [blame] | 96 | |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 97 | /* For clinval/clflush: record start and length of area */ |
| 98 | UInt guest_CMSTART; |
| 99 | UInt guest_CMLEN; |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 100 | |
| 101 | /* Used to record the unredirected guest address at the start of |
| 102 | a translation whose start has been redirected. By reading |
| 103 | this pseudo-register shortly afterwards, the translation can |
| 104 | find out what the corresponding no-redirection address was. |
| 105 | Note, this is only set for wrap-style redirects, not for |
| 106 | replace-style ones. */ |
| 107 | UInt guest_NRADDR; |
| 108 | |
| 109 | /* Needed for Darwin (but mandated for all guest architectures): |
| 110 | program counter at the last syscall insn (int 0x80/81/82, |
| 111 | sysenter, syscall, svc). Used when backing up to restart a |
| 112 | syscall that has been interrupted by a signal. */ |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 113 | /* 124 */ |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 114 | UInt guest_IP_AT_SYSCALL; |
| 115 | |
| 116 | /* VFP state. D0 .. D15 must be 8-aligned. */ |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 117 | /* 128 */ |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 118 | ULong guest_D0; |
| 119 | ULong guest_D1; |
| 120 | ULong guest_D2; |
| 121 | ULong guest_D3; |
| 122 | ULong guest_D4; |
| 123 | ULong guest_D5; |
| 124 | ULong guest_D6; |
| 125 | ULong guest_D7; |
| 126 | ULong guest_D8; |
| 127 | ULong guest_D9; |
| 128 | ULong guest_D10; |
| 129 | ULong guest_D11; |
| 130 | ULong guest_D12; |
| 131 | ULong guest_D13; |
| 132 | ULong guest_D14; |
| 133 | ULong guest_D15; |
sewardj | d266447 | 2010-08-22 12:44:20 +0000 | [diff] [blame] | 134 | ULong guest_D16; |
| 135 | ULong guest_D17; |
| 136 | ULong guest_D18; |
| 137 | ULong guest_D19; |
| 138 | ULong guest_D20; |
| 139 | ULong guest_D21; |
| 140 | ULong guest_D22; |
| 141 | ULong guest_D23; |
| 142 | ULong guest_D24; |
| 143 | ULong guest_D25; |
| 144 | ULong guest_D26; |
| 145 | ULong guest_D27; |
| 146 | ULong guest_D28; |
| 147 | ULong guest_D29; |
| 148 | ULong guest_D30; |
| 149 | ULong guest_D31; |
sewardj | 6c299f3 | 2009-12-31 18:00:12 +0000 | [diff] [blame] | 150 | UInt guest_FPSCR; |
| 151 | |
| 152 | /* Not a town in Cornwall, but instead the TPIDRURO, on of the |
| 153 | Thread ID registers present in CP15 (the system control |
| 154 | coprocessor), register set "c13", register 3 (the User |
| 155 | Read-only Thread ID Register). arm-linux apparently uses it |
| 156 | to hold the TLS pointer for the thread. It's read-only in |
| 157 | user space. On Linux it is set in user space by various |
| 158 | thread-related syscalls. */ |
| 159 | UInt guest_TPIDRURO; |
| 160 | |
sewardj | d266447 | 2010-08-22 12:44:20 +0000 | [diff] [blame] | 161 | /* Representation of the Thumb IT state. ITSTATE is a 32-bit |
| 162 | value with 4 8-bit lanes. [7:0] pertain to the next insn to |
| 163 | execute, [15:8] for the one after that, etc. The per-insn |
| 164 | update to ITSTATE is to unsignedly shift it right 8 bits, |
| 165 | hence introducing a zero byte for the furthest ahead |
| 166 | instruction. As per the next para, a zero byte denotes the |
| 167 | condition ALWAYS. |
| 168 | |
| 169 | Each byte lane has one of the two following formats: |
| 170 | |
| 171 | cccc 0001 for an insn which is part of an IT block. cccc is |
| 172 | the guarding condition (standard ARM condition |
| 173 | code) XORd with 0xE, so as to cause 'cccc == 0' |
| 174 | to encode the condition ALWAYS. |
| 175 | |
| 176 | 0000 0000 for an insn which is not part of an IT block. |
| 177 | |
| 178 | If the bottom 4 bits are zero then the top 4 must be too. |
| 179 | |
| 180 | Given the byte lane for an instruction, the guarding |
| 181 | condition for the instruction is (((lane >> 4) & 0xF) ^ 0xE). |
| 182 | This is not as stupid as it sounds, because the front end |
| 183 | elides the shift. And the am-I-in-an-IT-block check is |
| 184 | (lane != 0). |
| 185 | |
| 186 | In the case where (by whatever means) we know at JIT time |
| 187 | that an instruction is not in an IT block, we can prefix its |
| 188 | IR with assignments ITSTATE = 0 and hence have iropt fold out |
| 189 | the testing code. |
| 190 | |
| 191 | The condition "is outside or last in IT block" corresponds |
| 192 | to the top 24 bits of ITSTATE being zero. |
| 193 | */ |
| 194 | UInt guest_ITSTATE; |
| 195 | |
florian | 95a487b | 2014-02-14 08:55:32 +0000 | [diff] [blame] | 196 | /* Padding to make it have an 16-aligned size */ |
sewardj | d266447 | 2010-08-22 12:44:20 +0000 | [diff] [blame] | 197 | UInt padding1; |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 198 | } |
| 199 | VexGuestARMState; |
| 200 | |
| 201 | |
sewardj | fb183d2 | 2004-12-03 11:55:29 +0000 | [diff] [blame] | 202 | /*---------------------------------------------------------------*/ |
| 203 | /*--- Utility functions for ARM guest stuff. ---*/ |
| 204 | /*---------------------------------------------------------------*/ |
| 205 | |
| 206 | /* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */ |
| 207 | |
| 208 | /* Initialise all guest ARM state. */ |
| 209 | |
| 210 | extern |
| 211 | void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state ); |
| 212 | |
| 213 | /* Calculate the ARM flag state from the saved data. */ |
| 214 | |
| 215 | extern |
florian | efa834a | 2012-11-24 21:07:14 +0000 | [diff] [blame] | 216 | UInt LibVEX_GuestARM_get_cpsr ( /*IN*/const VexGuestARMState* vex_state ); |
sewardj | fb183d2 | 2004-12-03 11:55:29 +0000 | [diff] [blame] | 217 | |
| 218 | |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 219 | #endif /* ndef __LIBVEX_PUB_GUEST_ARM_H */ |
| 220 | |
sewardj | fb183d2 | 2004-12-03 11:55:29 +0000 | [diff] [blame] | 221 | |
sewardj | d584f8f | 2004-11-22 16:02:34 +0000 | [diff] [blame] | 222 | /*---------------------------------------------------------------*/ |
| 223 | /*--- libvex_guest_arm.h ---*/ |
| 224 | /*---------------------------------------------------------------*/ |