| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * This file contains common parts of x86-32 and x86-64 internals (inline | 8 * This file contains common parts of ia32 and x86-64 decoder and validator |
| 9 * functions and defines). | 9 * internals (inline functions which are used to pull useful information from |
| 10 * "well-known" bytes of the instruction: REX and VEX prefixes, ModR/M byte and |
| 11 * so on). |
| 10 * | 12 * |
| 11 * We only include simple schematic diagrams here. For full description see | 13 * See full description in AMD/Intel manuals. |
| 12 * AMD/Intel manuals. | |
| 13 */ | 14 */ |
| 14 | 15 |
| 15 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ | 16 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ |
| 16 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ | 17 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ |
| 17 | 18 |
| 18 #include "native_client/src/trusted/validator_ragel/decoder.h" | 19 #include "native_client/src/trusted/validator_ragel/decoder.h" |
| 19 | 20 |
| 20 #if NACL_WINDOWS | 21 #if NACL_WINDOWS |
| 21 # define FORCEINLINE __forceinline | 22 # define FORCEINLINE __forceinline |
| 22 #else | 23 #else |
| 23 # define FORCEINLINE __inline __attribute__ ((always_inline)) | 24 # define FORCEINLINE __inline __attribute__ ((always_inline)) |
| 24 #endif | 25 #endif |
| 25 | 26 |
| 26 | 27 |
| 27 /* | 28 /* |
| 28 * Opcode with register number embedded: | 29 * Opcode-with-register byte format: |
| 29 * | 30 * |
| 30 * 7 6 5 4 3 2 1 0 | 31 * bits 0-2: register number |
| 31 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 32 * bits 3-7: actual opcode |
| 32 * │ Opcode │ register number ┃ | |
| 33 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
| 34 */ | 33 */ |
| 35 static FORCEINLINE uint8_t RegFromOpcode(uint8_t modrm) { | 34 static FORCEINLINE uint8_t RegFromOpcode(uint8_t modrm) { |
| 36 return modrm & 0x07; | 35 return modrm & 0x07; |
| 37 } | 36 } |
| 38 | 37 |
| 39 /* | 38 /* |
| 40 * ModRM byte format: | 39 * ModRM byte format: |
| 41 * | 40 * |
| 42 * 7 6 5 4 3 2 1 0 | 41 * bits 0-2: r/m |
| 43 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 42 * bits 3-5: reg |
| 44 * │ mod │ reg │ r/m ┃ | 43 * bits 6-7: mod |
| 45 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
| 46 */ | 44 */ |
| 47 static FORCEINLINE uint8_t ModFromModRM(uint8_t modrm) { | 45 static FORCEINLINE uint8_t ModFromModRM(uint8_t modrm) { |
| 48 return modrm >> 6; | 46 return modrm >> 6; |
| 49 } | 47 } |
| 50 | 48 |
| 51 static FORCEINLINE uint8_t RegFromModRM(uint8_t modrm) { | 49 static FORCEINLINE uint8_t RegFromModRM(uint8_t modrm) { |
| 52 return (modrm & 0x38) >> 3; | 50 return (modrm >> 3) & 0x07; |
| 53 } | 51 } |
| 54 | 52 |
| 55 static FORCEINLINE uint8_t RMFromModRM(uint8_t modrm) { | 53 static FORCEINLINE uint8_t RMFromModRM(uint8_t modrm) { |
| 56 return modrm & 0x07; | 54 return modrm & 0x07; |
| 57 } | 55 } |
| 58 | 56 |
| 59 /* | 57 /* |
| 60 * SIB byte format: | 58 * SIB byte format: |
| 61 * | 59 * |
| 62 * 7 6 5 4 3 2 1 0 | 60 * bits 0-2: base |
| 63 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 61 * bits 3-5: index |
| 64 * │ scale │ index │ base ┃ | 62 * bits 6-7: scale |
| 65 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
| 66 */ | 63 */ |
| 67 static FORCEINLINE uint8_t ScaleFromSIB(uint8_t sib) { | 64 static FORCEINLINE uint8_t ScaleFromSIB(uint8_t sib) { |
| 68 return sib >> 6; | 65 return sib >> 6; |
| 69 } | 66 } |
| 70 | 67 |
| 71 static FORCEINLINE uint8_t IndexFromSIB(uint8_t sib) { | 68 static FORCEINLINE uint8_t IndexFromSIB(uint8_t sib) { |
| 72 return (sib & 0x38) >> 3; | 69 return (sib >> 3) & 0x07; |
| 73 } | 70 } |
| 74 | 71 |
| 75 static FORCEINLINE uint8_t BaseFromSIB(uint8_t sib) { | 72 static FORCEINLINE uint8_t BaseFromSIB(uint8_t sib) { |
| 76 return sib & 0x07; | 73 return sib & 0x07; |
| 77 } | 74 } |
| 78 | 75 |
| 79 /* | 76 /* |
| 80 * REX byte format: | 77 * REX byte format: |
| 81 * | 78 * |
| 82 * 7 6 5 4 3 2 1 0 | 79 * bit 0: B (Base) |
| 83 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 80 * bit 1: X (indeX) |
| 84 * │ 0 │ 1 │ 0 │ 0 │ W │ R │ X │ B ┃ | 81 * bit 2: R (Register) |
| 85 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 82 * bit 3: W (Wide) |
| 83 * 4-7 bits: 0x4 (REX signature) |
| 86 */ | 84 */ |
| 87 | 85 |
| 88 enum { | 86 enum { |
| 89 REX_B = 1, | 87 REX_B = 1, |
| 90 REX_X = 2, | 88 REX_X = 2, |
| 91 REX_R = 4, | 89 REX_R = 4, |
| 92 REX_W = 8 | 90 REX_W = 8 |
| 93 }; | 91 }; |
| 94 | 92 |
| 93 /* How much to add to "base register" number: 0 or 8 */ |
| 95 static FORCEINLINE uint8_t BaseExtentionFromREX(uint8_t rex) { | 94 static FORCEINLINE uint8_t BaseExtentionFromREX(uint8_t rex) { |
| 96 return (rex & REX_B) << 3; | 95 return (rex & REX_B) << 3; |
| 97 } | 96 } |
| 98 | 97 |
| 98 /* How much to add to "index register" number: 0 or 8 */ |
| 99 static FORCEINLINE uint8_t IndexExtentionFromREX(uint8_t rex) { | 99 static FORCEINLINE uint8_t IndexExtentionFromREX(uint8_t rex) { |
| 100 return (rex & REX_X) << 2; | 100 return (rex & REX_X) << 2; |
| 101 } | 101 } |
| 102 | 102 |
| 103 /* How much to add to "register operand" number: 0 or 8 */ |
| 103 static FORCEINLINE uint8_t RegisterExtentionFromREX(uint8_t rex) { | 104 static FORCEINLINE uint8_t RegisterExtentionFromREX(uint8_t rex) { |
| 104 return (rex & REX_R) << 1; | 105 return (rex & REX_R) << 1; |
| 105 } | 106 } |
| 106 | 107 |
| 107 /* | 108 /* |
| 108 * VEX 2nd byte format: | 109 * VEX 2nd byte format: |
| 109 * | 110 * |
| 110 * 7 6 5 4 3 2 1 0 | 111 * bits 0-4: opcode selector |
| 111 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 112 * bit 5: inverted B (Base) |
| 112 * │ ¬R │ ¬X │ ¬B │ opcode map selector ┃ | 113 * bit 6: inverted X (indeX) |
| 113 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 114 * bit 7: inverted R (Register) |
| 115 * |
| 114 */ | 116 */ |
| 115 | 117 |
| 116 enum { | 118 enum { |
| 117 VEX_MAP1 = 0x01, | 119 VEX_MAP1 = 0x01, |
| 118 VEX_MAP2 = 0x02, | 120 VEX_MAP2 = 0x02, |
| 119 VEX_MAP3 = 0x03, | 121 VEX_MAP3 = 0x03, |
| 120 VEX_MAP8 = 0x08, | 122 VEX_MAP8 = 0x08, |
| 121 VEX_MAP9 = 0x09, | 123 VEX_MAP9 = 0x09, |
| 122 VEX_MAPA = 0x0a, | 124 VEX_MAPA = 0x0a, |
| 123 VEX_B = 0x20, | 125 VEX_B = 0x20, |
| 124 VEX_X = 0x40, | 126 VEX_X = 0x40, |
| 125 VEX_R = 0x80, | 127 VEX_R = 0x80 |
| 126 VEX_W = 0x80 | |
| 127 }; | 128 }; |
| 128 | 129 |
| 130 /* How much to add to "base register" number: 0 or 8 */ |
| 129 static FORCEINLINE uint8_t BaseExtentionFromVEX(uint8_t vex2) { | 131 static FORCEINLINE uint8_t BaseExtentionFromVEX(uint8_t vex2) { |
| 130 return ((~vex2) & VEX_B) >> 2; | 132 return ((~vex2) & VEX_B) >> 2; |
| 131 } | 133 } |
| 132 | 134 |
| 135 /* How much to add to "index register" number: 0 or 8 */ |
| 133 static FORCEINLINE uint8_t IndexExtentionFromVEX(uint8_t vex2) { | 136 static FORCEINLINE uint8_t IndexExtentionFromVEX(uint8_t vex2) { |
| 134 return ((~vex2) & VEX_X) >> 3; | 137 return ((~vex2) & VEX_X) >> 3; |
| 135 } | 138 } |
| 136 | 139 |
| 140 /* How much to add to "register operand" number: 0 or 8 */ |
| 137 static FORCEINLINE uint8_t RegisterExtentionFromVEX(uint8_t vex2) { | 141 static FORCEINLINE uint8_t RegisterExtentionFromVEX(uint8_t vex2) { |
| 138 return ((~vex2) & VEX_R) >> 4; | 142 return ((~vex2) & VEX_R) >> 4; |
| 139 } | 143 } |
| 140 | 144 |
| 141 /* | 145 /* |
| 142 * VEX 3rd byte format: | 146 * VEX 3rd byte format: |
| 143 * | 147 * |
| 144 * 7 6 5 4 3 2 1 0 | 148 * bits 0-1: pp (Packed Prefix) |
| 145 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 149 * bit 2: L (Long) |
| 146 * │ W │ ¬vvvv (register number) │ L │ pp ┃ | 150 * bits 3-6: negated vvvv (register number) |
| 147 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 151 * bit 7: W (Wide) |
| 148 */ | 152 */ |
| 149 | 153 |
| 154 enum { |
| 155 VEX_PP_NONE = 0x00, |
| 156 VEX_PP_0X66 = 0x01, |
| 157 VEX_PP_0XF3 = 0x02, |
| 158 VEX_PP_0XF2 = 0x03, |
| 159 VEX_L = 0x04, |
| 160 VEX_VVVV = 0x78, |
| 161 VEX_W = 0x80 |
| 162 }; |
| 163 |
| 164 |
| 150 static FORCEINLINE uint8_t GetOperandFromVexIA32(uint8_t vex3) { | 165 static FORCEINLINE uint8_t GetOperandFromVexIA32(uint8_t vex3) { |
| 151 return ((~vex3) & 0x38) >> 3; | 166 return ((~vex3) & VEX_VVVV) >> 3; |
| 152 } | 167 } |
| 153 | 168 |
| 154 static FORCEINLINE uint8_t GetOperandFromVexAMD64(uint8_t vex3) { | 169 static FORCEINLINE uint8_t GetOperandFromVexAMD64(uint8_t vex3) { |
| 155 return ((~vex3) & 0x78) >> 3; | 170 return ((~vex3) & VEX_VVVV) >> 3; |
| 156 } | 171 } |
| 157 | 172 |
| 158 /* | 173 /* |
| 159 * is4 byte format: | 174 * is4/is5 byte format: |
| 160 * | 175 * |
| 161 * 7 6 5 4 3 2 1 0 | 176 * bits 0-1: imm2 or zero |
| 162 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 177 * bits 2-3: 0 |
| 163 * │ vvvv (register number) │ 0 │ 0 │ imm2 or zero ┃ | 178 * bits 4-7: register number |
| 164 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | |
| 165 */ | 179 */ |
| 166 static FORCEINLINE uint8_t RegisterFromIS4(uint8_t is4) { | 180 static FORCEINLINE uint8_t RegisterFromIS4(uint8_t is4) { |
| 167 return is4 >> 4; | 181 return is4 >> 4; |
| 168 } | 182 } |
| 169 | 183 |
| 170 /* | 184 /* |
| 171 * SignExtendXXBit is used to sign-extend XX-bit value to unsigned 64-bit value. | 185 * SignExtendXXBit is used to sign-extend XX-bit value to unsigned 64-bit value. |
| 172 * | 186 * |
| 173 * To do that you need to pass unsigned value of smaller then 64-bit size | 187 * To do that you need to pass unsigned value of smaller then 64-bit size |
| 174 * to this function: it will be converted to signed value and then | 188 * to this function: it will be converted to signed value and then |
| 175 * sign-extended to become 64-bit value. | 189 * sign-extended to become 64-bit value. |
| 176 * | 190 * |
| 177 * Smaller values can be obtained by restricting this value further (which is | 191 * Return values can be restricted to smaller unsigned type when needed (which |
| 178 * safe according to the C language specification: see 6.2.1.2 in C90 and | 192 * is safe according to the C language specification: see 6.2.1.2 in C90 and |
| 179 * 6.3.1.3.2 in C99 specification). | 193 * 6.3.1.3.2 in C99 specification). |
| 180 * | 194 * |
| 181 * Note that these operations are safe but slightly unusual: they come very | 195 * Note that these operations are safe but slightly unusual: they come very |
| 182 * close to the edge of what "well-behaved C program is not supposed to do", | 196 * close to the edge of what "well-behaved C program is not supposed to do", |
| 183 * but they stay on the "safe" side of this boundary. Specifically: this | 197 * but they stay on the "safe" side of this boundary. Specifically: this |
| 184 * behavior triggers "implementation-defined behavior" (see 6.2.1.2 in C90 | 198 * (conversion to intXX_t) behavior triggers "implementation-defined behavior" |
| 185 * specification and 6.3.1.3.3 in C99 specification) which sounds suspiciously | 199 * (see 6.2.1.2 in C90 specification and 6.3.1.3.3 in C99 specification) which |
| 186 * similar to the dreaded "undefined behavior", but in reality these two are | 200 * sounds suspiciously similar to the dreaded "undefined behavior", but in |
| 187 * quite different: any program which triggers "undefined behavior" is not a | 201 * reality these two are quite different: any program which triggers "undefined |
| 188 * valid C program at all, but program which triggers "implementation-defined | 202 * behavior" is not a valid C program at all, but program which triggers |
| 189 * behavior" is quite valid C program. What this program actually *does* | 203 * "implementation-defined behavior" is quite valid C program. What this |
| 190 * depends on the specification of a given C compiler: each particular | 204 * program actually *does* depends on the specification of a given C compiler: |
| 191 * implementation must decide for itself what it'll do in this particular case | 205 * each particular implementation must decide for itself what it'll do in this |
| 192 * and *stick* *to* *it*. If the implementation uses two's-complement negative | 206 * particular case and *stick* *to* *it*. If the implementation actually uses |
| 193 * numbers (and all the implementation which can compile this code *must* | 207 * two's-complement negative numbers (and all the implementation which can |
| 194 * support two's-complement arythmetic - see 7.18.1.1 in C99 specification) then | 208 * compile this code *must* support two's-complement arythmetic - see 7.18.1.1 |
| 195 * the easiest thing to do is to do what we need here - this is what all known | 209 * in C99 specification) then the easiest thing to do is to do what we need |
| 196 * compilers for all known platforms are actually doing. | 210 * here - this is what all known compilers for all known platforms are actually |
| 211 * doing. |
| 212 * |
| 213 * Conversion from intXX_t to uint64_t is always safe (same as before: see |
| 214 * see 6.2.1.2 in C90 specification and 6.3.1.3.2 in C99 specification). |
| 197 */ | 215 */ |
| 198 static FORCEINLINE uint64_t SignExtend8Bit(uint64_t value) { | 216 static FORCEINLINE uint64_t SignExtend8Bit(uint64_t value) { |
| 199 return (int8_t)value; | 217 return (int8_t)value; |
| 200 } | 218 } |
| 201 | 219 |
| 202 static FORCEINLINE uint64_t SignExtend16Bit(uint64_t value) { | 220 static FORCEINLINE uint64_t SignExtend16Bit(uint64_t value) { |
| 203 return (int16_t)value; | 221 return (int16_t)value; |
| 204 } | 222 } |
| 205 | 223 |
| 206 static FORCEINLINE uint64_t SignExtend32Bit(uint64_t value) { | 224 static FORCEINLINE uint64_t SignExtend32Bit(uint64_t value) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 226 | 244 |
| 227 static const uint8_t index_registers[] = { | 245 static const uint8_t index_registers[] = { |
| 228 /* Note how REG_RIZ falls out of the pattern. */ | 246 /* Note how REG_RIZ falls out of the pattern. */ |
| 229 REG_RAX, REG_RCX, REG_RDX, REG_RBX, | 247 REG_RAX, REG_RCX, REG_RDX, REG_RBX, |
| 230 REG_RIZ, REG_RBP, REG_RSI, REG_RDI, | 248 REG_RIZ, REG_RBP, REG_RSI, REG_RDI, |
| 231 REG_R8, REG_R9, REG_R10, REG_R11, | 249 REG_R8, REG_R9, REG_R10, REG_R11, |
| 232 REG_R12, REG_R13, REG_R14, REG_R15 | 250 REG_R12, REG_R13, REG_R14, REG_R15 |
| 233 }; | 251 }; |
| 234 | 252 |
| 235 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ */ | 253 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ */ |
| OLD | NEW |