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 x86-32 and x86-64 internals (inline |
9 * functions and defines). | 9 * functions and defines). |
Vlad Shcherbina
2013/03/13 15:17:15
Copy-paste! Please be more explicit about what is
khim
2013/03/19 14:54:46
Done.
| |
10 * | 10 * |
11 * We only include simple schematic diagrams here. For full description see | 11 * We only include simple schematic diagrams here. For full description see |
halyavin
2013/03/14 13:48:44
See full description in AMD/Intel manuals.
khim
2013/03/19 14:54:46
Done.
| |
12 * AMD/Intel manuals. | 12 * AMD/Intel manuals. |
13 */ | 13 */ |
14 | 14 |
15 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ | 15 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ |
16 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ | 16 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ |
17 | 17 |
18 #include "native_client/src/trusted/validator_ragel/decoder.h" | 18 #include "native_client/src/trusted/validator_ragel/decoder.h" |
19 | 19 |
20 #if NACL_WINDOWS | 20 #if NACL_WINDOWS |
21 # define FORCEINLINE __forceinline | 21 # define FORCEINLINE __forceinline |
22 #else | 22 #else |
23 # define FORCEINLINE __inline __attribute__ ((always_inline)) | 23 # define FORCEINLINE __inline __attribute__ ((always_inline)) |
24 #endif | 24 #endif |
25 | 25 |
26 | 26 |
27 /* | 27 /* |
28 * Opcode with register number embedded: | 28 * Opcode with register number embedded: |
29 * | 29 * |
30 * 7 6 5 4 3 2 1 0 | 30 * 7 6 5 4 3 2 1 0 |
31 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 31 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
halyavin
2013/03/14 13:48:44
0-2 bits: register number
3-7 bits: opcode
khim
2013/03/19 14:54:46
Done.
| |
32 * │ Opcode │ register number ┃ | 32 * │ Opcode │ register number ┃ |
33 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 33 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
34 */ | 34 */ |
35 static FORCEINLINE uint8_t RegFromOpcode(uint8_t modrm) { | 35 static FORCEINLINE uint8_t RegFromOpcode(uint8_t modrm) { |
36 return modrm & 0x07; | 36 return modrm & 0x07; |
37 } | 37 } |
38 | 38 |
39 /* | 39 /* |
40 * ModRM byte format: | 40 * ModRM byte format: |
41 * | 41 * |
halyavin
2013/03/14 13:48:44
0-2 bits: r/m
3-5 bits: reg
6-7 bits: mod
khim
2013/03/19 14:54:46
Done.
| |
42 * 7 6 5 4 3 2 1 0 | 42 * 7 6 5 4 3 2 1 0 |
43 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 43 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
44 * │ mod │ reg │ r/m ┃ | 44 * │ mod │ reg │ r/m ┃ |
45 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 45 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
46 */ | 46 */ |
47 static FORCEINLINE uint8_t ModFromModRM(uint8_t modrm) { | 47 static FORCEINLINE uint8_t ModFromModRM(uint8_t modrm) { |
48 return modrm >> 6; | 48 return modrm >> 6; |
49 } | 49 } |
50 | 50 |
51 static FORCEINLINE uint8_t RegFromModRM(uint8_t modrm) { | 51 static FORCEINLINE uint8_t RegFromModRM(uint8_t modrm) { |
52 return (modrm & 0x38) >> 3; | 52 return (modrm & 0x38) >> 3; |
halyavin
2013/03/14 13:48:44
(modrm >> 3) & 0x07 is easier to understand.
khim
2013/03/19 14:54:46
Done.
| |
53 } | 53 } |
54 | 54 |
55 static FORCEINLINE uint8_t RMFromModRM(uint8_t modrm) { | 55 static FORCEINLINE uint8_t RMFromModRM(uint8_t modrm) { |
56 return modrm & 0x07; | 56 return modrm & 0x07; |
57 } | 57 } |
58 | 58 |
59 /* | 59 /* |
60 * SIB byte format: | 60 * SIB byte format: |
61 * | 61 * |
halyavin
2013/03/14 13:48:44
0-2 bits: base
3-5 bits: index
6-7 bits: scale
khim
2013/03/19 14:54:46
Done.
| |
62 * 7 6 5 4 3 2 1 0 | 62 * 7 6 5 4 3 2 1 0 |
63 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 63 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
64 * │ scale │ index │ base ┃ | 64 * │ scale │ index │ base ┃ |
65 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 65 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
66 */ | 66 */ |
67 static FORCEINLINE uint8_t ScaleFromSIB(uint8_t sib) { | 67 static FORCEINLINE uint8_t ScaleFromSIB(uint8_t sib) { |
68 return sib >> 6; | 68 return sib >> 6; |
69 } | 69 } |
70 | 70 |
71 static FORCEINLINE uint8_t IndexFromSIB(uint8_t sib) { | 71 static FORCEINLINE uint8_t IndexFromSIB(uint8_t sib) { |
72 return (sib & 0x38) >> 3; | 72 return (sib & 0x38) >> 3; |
halyavin
2013/03/14 13:48:44
(sib >> 3) & 0x07 is easier to understand.
khim
2013/03/19 14:54:46
Done.
| |
73 } | 73 } |
74 | 74 |
75 static FORCEINLINE uint8_t BaseFromSIB(uint8_t sib) { | 75 static FORCEINLINE uint8_t BaseFromSIB(uint8_t sib) { |
76 return sib & 0x07; | 76 return sib & 0x07; |
77 } | 77 } |
78 | 78 |
79 /* | 79 /* |
80 * REX byte format: | 80 * REX byte format: |
81 * | 81 * |
halyavin
2013/03/14 13:48:44
0 bit: B
1 bit: X
2 bit: R
3 bit: W
4-7 bits: 0x4
khim
2013/03/19 14:54:46
Done.
| |
82 * 7 6 5 4 3 2 1 0 | 82 * 7 6 5 4 3 2 1 0 |
83 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 83 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
84 * │ 0 │ 1 │ 0 │ 0 │ W │ R │ X │ B ┃ | 84 * │ 0 │ 1 │ 0 │ 0 │ W │ R │ X │ B ┃ |
85 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 85 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
86 */ | 86 */ |
87 | 87 |
88 enum { | 88 enum { |
89 REX_B = 1, | 89 REX_B = 1, |
90 REX_X = 2, | 90 REX_X = 2, |
91 REX_R = 4, | 91 REX_R = 4, |
92 REX_W = 8 | 92 REX_W = 8 |
93 }; | 93 }; |
94 | 94 |
95 static FORCEINLINE uint8_t BaseExtentionFromREX(uint8_t rex) { | 95 static FORCEINLINE uint8_t BaseExtentionFromREX(uint8_t rex) { |
halyavin
2013/03/14 13:48:44
/* How much to add to base register number. */
th
khim
2013/03/19 14:54:46
Done.
| |
96 return (rex & REX_B) << 3; | 96 return (rex & REX_B) << 3; |
97 } | 97 } |
98 | 98 |
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 static FORCEINLINE uint8_t RegisterExtentionFromREX(uint8_t rex) { | 103 static FORCEINLINE uint8_t RegisterExtentionFromREX(uint8_t rex) { |
104 return (rex & REX_R) << 1; | 104 return (rex & REX_R) << 1; |
105 } | 105 } |
106 | 106 |
107 /* | 107 /* |
108 * VEX 2nd byte format: | 108 * VEX 2nd byte format: |
109 * | 109 * |
halyavin
2013/03/14 13:48:44
0-4 bits: opcode selector
5 bit: inverted B
6 bit:
khim
2013/03/19 14:54:46
Done.
| |
110 * 7 6 5 4 3 2 1 0 | 110 * 7 6 5 4 3 2 1 0 |
111 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 111 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
112 * │ ¬R │ ¬X │ ¬B │ opcode map selector ┃ | 112 * │ ¬R │ ¬X │ ¬B │ opcode map selector ┃ |
113 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 113 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
114 */ | 114 */ |
115 | 115 |
116 enum { | 116 enum { |
117 VEX_MAP1 = 0x01, | 117 VEX_MAP1 = 0x01, |
118 VEX_MAP2 = 0x02, | 118 VEX_MAP2 = 0x02, |
119 VEX_MAP3 = 0x03, | 119 VEX_MAP3 = 0x03, |
(...skipping 13 matching lines...) Expand all Loading... | |
133 static FORCEINLINE uint8_t IndexExtentionFromVEX(uint8_t vex2) { | 133 static FORCEINLINE uint8_t IndexExtentionFromVEX(uint8_t vex2) { |
134 return ((~vex2) & VEX_X) >> 3; | 134 return ((~vex2) & VEX_X) >> 3; |
135 } | 135 } |
136 | 136 |
137 static FORCEINLINE uint8_t RegisterExtentionFromVEX(uint8_t vex2) { | 137 static FORCEINLINE uint8_t RegisterExtentionFromVEX(uint8_t vex2) { |
138 return ((~vex2) & VEX_R) >> 4; | 138 return ((~vex2) & VEX_R) >> 4; |
139 } | 139 } |
140 | 140 |
141 /* | 141 /* |
142 * VEX 3rd byte format: | 142 * VEX 3rd byte format: |
143 * | 143 * |
halyavin
2013/03/14 13:48:44
0-1 bits: pp
2 bit: L
3-6 bits: inverted register
khim
2013/03/19 14:54:46
Done.
| |
144 * 7 6 5 4 3 2 1 0 | 144 * 7 6 5 4 3 2 1 0 |
145 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 145 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
146 * │ W │ ¬vvvv (register number) │ L │ pp ┃ | 146 * │ W │ ¬vvvv (register number) │ L │ pp ┃ |
147 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 147 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
148 */ | 148 */ |
149 | 149 |
150 static FORCEINLINE uint8_t GetOperandFromVexIA32(uint8_t vex3) { | 150 static FORCEINLINE uint8_t GetOperandFromVexIA32(uint8_t vex3) { |
151 return ((~vex3) & 0x38) >> 3; | 151 return ((~vex3) & 0x38) >> 3; |
halyavin
2013/03/14 13:48:44
((~vex3) >> 3) & 0x07 is easier to understand
khim
2013/03/19 14:54:46
Done.
| |
152 } | 152 } |
153 | 153 |
154 static FORCEINLINE uint8_t GetOperandFromVexAMD64(uint8_t vex3) { | 154 static FORCEINLINE uint8_t GetOperandFromVexAMD64(uint8_t vex3) { |
155 return ((~vex3) & 0x78) >> 3; | 155 return ((~vex3) & 0x78) >> 3; |
halyavin
2013/03/14 13:48:44
((~vex3) >> 3) & 0x0f is easier to understand
khim
2013/03/19 14:54:46
Done.
| |
156 } | 156 } |
157 | 157 |
158 /* | 158 /* |
159 * is4 byte format: | 159 * is4 byte format: |
160 * | 160 * |
halyavin
2013/03/14 13:48:44
0-1 bits: imm2 or zero
2-3 bits: 0
4-7 bits: regis
khim
2013/03/19 14:54:46
Done.
| |
161 * 7 6 5 4 3 2 1 0 | 161 * 7 6 5 4 3 2 1 0 |
162 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ | 162 * ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┒ |
163 * │ vvvv (register number) │ 0 │ 0 │ imm2 or zero ┃ | 163 * │ vvvv (register number) │ 0 │ 0 │ imm2 or zero ┃ |
164 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ | 164 * ┕━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┷━━━━━━━┛ |
165 */ | 165 */ |
166 static FORCEINLINE uint8_t RegisterFromIS4(uint8_t is4) { | 166 static FORCEINLINE uint8_t RegisterFromIS4(uint8_t is4) { |
167 return is4 >> 4; | 167 return is4 >> 4; |
168 } | 168 } |
169 | 169 |
170 /* | 170 /* |
171 * SignExtendXXBit is used to sign-extend XX-bit value to unsigned 64-bit value. | 171 * SignExtendXXBit is used to sign-extend XX-bit value to unsigned 64-bit value. |
172 * | 172 * |
173 * To do that you need to pass unsigned value of smaller then 64-bit size | 173 * 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 | 174 * to this function: it will be converted to signed value and then |
175 * sign-extended to become 64-bit value. | 175 * sign-extended to become 64-bit value. |
176 * | 176 * |
177 * Smaller values can be obtained by restricting this value further (which is | 177 * Smaller values can be obtained by restricting this value further (which is |
halyavin
2013/03/14 13:48:44
Return values can be restricted to smaller unsigne
khim
2013/03/19 14:54:46
Done.
| |
178 * safe according to the C language specification: see 6.2.1.2 in C90 and | 178 * safe according to the C language specification: see 6.2.1.2 in C90 and |
179 * 6.3.1.3.2 in C99 specification). | 179 * 6.3.1.3.2 in C99 specification). |
180 * | 180 * |
181 * Note that these operations are safe but slightly unusual: they come very | 181 * 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", | 182 * 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 | 183 * but they stay on the "safe" side of this boundary. Specifically: this |
halyavin
2013/03/14 13:48:44
this (conversion to intXX_t)
khim
2013/03/19 14:54:46
Done.
| |
184 * behavior triggers "implementation-defined behavior" (see 6.2.1.2 in C90 | 184 * behavior triggers "implementation-defined behavior" (see 6.2.1.2 in C90 |
185 * specification and 6.3.1.3.3 in C99 specification) which sounds suspiciously | 185 * specification and 6.3.1.3.3 in C99 specification) which sounds suspiciously |
186 * similar to the dreaded "undefined behavior", but in reality these two are | 186 * similar to the dreaded "undefined behavior", but in reality these two are |
187 * quite different: any program which triggers "undefined behavior" is not a | 187 * quite different: any program which triggers "undefined behavior" is not a |
188 * valid C program at all, but program which triggers "implementation-defined | 188 * valid C program at all, but program which triggers "implementation-defined |
189 * behavior" is quite valid C program. What this program actually *does* | 189 * behavior" is quite valid C program. What this program actually *does* |
190 * depends on the specification of a given C compiler: each particular | 190 * depends on the specification of a given C compiler: each particular |
191 * implementation must decide for itself what it'll do in this particular case | 191 * implementation must decide for itself what it'll do in this particular case |
192 * and *stick* *to* *it*. If the implementation uses two's-complement negative | 192 * and *stick* *to* *it*. If the implementation uses two's-complement negative |
193 * numbers (and all the implementation which can compile this code *must* | 193 * numbers (and all the implementation which can compile this code *must* |
194 * support two's-complement arythmetic - see 7.18.1.1 in C99 specification) then | 194 * support two's-complement arythmetic - see 7.18.1.1 in C99 specification) then |
195 * the easiest thing to do is to do what we need here - this is what all known | 195 * the easiest thing to do is to do what we need here - this is what all known |
196 * compilers for all known platforms are actually doing. | 196 * compilers for all known platforms are actually doing. |
halyavin
2013/03/14 13:48:44
Mention that conversion from intXX_t to uint64_t i
khim
2013/03/19 14:54:46
Done.
| |
197 */ | 197 */ |
198 static FORCEINLINE uint64_t SignExtend8Bit(uint64_t value) { | 198 static FORCEINLINE uint64_t SignExtend8Bit(uint64_t value) { |
199 return (int8_t)value; | 199 return (int8_t)value; |
200 } | 200 } |
201 | 201 |
202 static FORCEINLINE uint64_t SignExtend16Bit(uint64_t value) { | 202 static FORCEINLINE uint64_t SignExtend16Bit(uint64_t value) { |
203 return (int16_t)value; | 203 return (int16_t)value; |
204 } | 204 } |
205 | 205 |
206 static FORCEINLINE uint64_t SignExtend32Bit(uint64_t value) { | 206 static FORCEINLINE uint64_t SignExtend32Bit(uint64_t value) { |
(...skipping 19 matching lines...) Expand all Loading... | |
226 | 226 |
227 static const uint8_t index_registers[] = { | 227 static const uint8_t index_registers[] = { |
228 /* Note how REG_RIZ falls out of the pattern. */ | 228 /* Note how REG_RIZ falls out of the pattern. */ |
229 REG_RAX, REG_RCX, REG_RDX, REG_RBX, | 229 REG_RAX, REG_RCX, REG_RDX, REG_RBX, |
230 REG_RIZ, REG_RBP, REG_RSI, REG_RDI, | 230 REG_RIZ, REG_RBP, REG_RSI, REG_RDI, |
231 REG_R8, REG_R9, REG_R10, REG_R11, | 231 REG_R8, REG_R9, REG_R10, REG_R11, |
232 REG_R12, REG_R13, REG_R14, REG_R15 | 232 REG_R12, REG_R13, REG_R14, REG_R15 |
233 }; | 233 }; |
234 | 234 |
235 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ */ | 235 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_DECODING_H_ */ |
OLD | NEW |